Update Dart dependencies, remove override for 'usage' package

This updates Dart packages and removes the override for the 'usage'
package. This was pinned due to a crash when LANG was unset, but based
on local testing this doesn't seem to be needed any more.

Change-Id: I524639d73cf4b3807dd248b801696734248a580a
diff --git a/dart_dependencies.yaml b/dart_dependencies.yaml
index 5122496..80fce84 100644
--- a/dart_dependencies.yaml
+++ b/dart_dependencies.yaml
@@ -7,6 +7,3 @@
 
 name: emergency_deps
 dependencies:
-  # 3.1.0 uses Platform.localeName which crashes if the LANG environment
-  # variable is not set, which is the case on bots.
-  usage: 3.0.1
diff --git a/importer/importer.py b/importer/importer.py
index dada220..f3fbce6 100755
--- a/importer/importer.py
+++ b/importer/importer.py
@@ -30,6 +30,7 @@
   'func' : '//dart/third_party/pkg/func',
   'kernel': '//dart/pkg/kernel',
   'linter': '//dart/third_party/pkg/linter',
+  'telemetry': '//dart/pkg/telemetry',
   'typed_mock': '//dart/pkg/typed_mock',
 }
 
diff --git a/pub/archive/BUILD.gn b/pub/archive/BUILD.gn
index e3bf1d1..8762ac8 100644
--- a/pub/archive/BUILD.gn
+++ b/pub/archive/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for archive-1.0.29
+# This file is generated by importer.py for archive-1.0.31
 
 import("//build/dart/dart_package.gni")
 
@@ -10,6 +10,7 @@
   disable_analysis = true
 
   deps = [
+    "//third_party/dart-pkg/pub/path",
     "//third_party/dart-pkg/pub/args",
     "//third_party/dart-pkg/pub/crypto",
   ]
diff --git a/pub/archive/CHANGELOG.md b/pub/archive/CHANGELOG.md
new file mode 100755
index 0000000..83dec86
--- /dev/null
+++ b/pub/archive/CHANGELOG.md
@@ -0,0 +1,60 @@
+## 1.0.30 - May 27, 2017

+

+- Add archive_io sub-package for supporting file streaming rather than storing everything in memory.

+  **This is a work-in-progress and under development.**

+

+## 1.0.29 - May 25, 2017

+

+- Fix issue with POSIX tar files.

+- Upgrade dependency on `archive` to `>=1.0.0 <2.0.0`

+

+## 1.0.20 - Jun2 21, 2015

+

+- Improve performance decompressing large files in zip archives.

+

+## 1.0.19 - February 23, 2014

+

+- Disable CRC verification by default when decoding archives.

+

+## 1.0.18 - October 09, 2014

+

+- Add support for encoding uncompressed files in zip archives.

+

+## 1.0.17 - April 25, 2014

+

+- Fix a bug in InputStream.

+

+## 1.0.16 - March 02, 2014

+

+- Add stream support to Inflate decompression.

+

+## 1.0.15 - February 16, 2014

+

+- Improved performance when writing large blocks.

+

+## 1.0.14 - February 12, 2014

+

+- Misc updates and fixes.

+

+## 1.0.13 - February 06, 2014

+

+- Added BZip2 encoder.

+

+- *BREAKING CHANGE*: `File` was renamed to `ArchiveFile`, to avoid conflicts with

+  `dart:io`.

+

+## 1.0.12 - February 04, 2014

+

+- Added BZip2 decoder.

+

+## 1.0.11 - February 02, 2014

+

+- Changed `InputStream` to work with typed_data instead of `List<int>`, should

+  reduce memory and increase performance.

+

+## 1.0.10 - January 19, 2013

+

+- Renamed `InputBuffer` and `OutputBuffer` to `InputStream` and `OutputStream`,

+  respectively.

+

+- Added `readBits` method to `InputStream`.

diff --git a/pub/archive/ChangeLog.txt b/pub/archive/ChangeLog.txt
deleted file mode 100755
index 66c8b0a..0000000
--- a/pub/archive/ChangeLog.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-v 1.0.29 - May 25, 2017

-

-- Fix issue with POSIX tar files.

-

-- Upgrade dependency on archive to `>=1.0.0 <2.0.0`

-

-v 1.0.20 - Jun2 21, 2015

-

-- Improve performance decompressing large files in zip archives.

-

-

-v 1.0.19 - February 23, 2014

-

-- Disable CRC verification by default when decoding archives.

-

-

-v 1.0.18 - October 09, 2014

-

-- Add support for encoding uncompressed files in zip archives.

-

-

-v 1.0.17 - April 25, 2014

-

-- Fix a bug in InputStream.

-

-

-v 1.0.16 - March 02, 2014

-

-- Add stream support to Inflate decompression.

-

-

-v 1.0.15 - February 16, 2014

-

-- Improved performance when writing large blocks.

-

-

-v 1.0.14 - February 12, 2014

-

-- Misc updates and fixes.

-

-

-v 1.0.13 - February 06, 2014

-

-- Added BZip2 encoder.

-

-- *BREAKING CHANGE*: File was renamed to ArchiveFile, to avoid conflicts with

-  dart:io.

-

-

-v 1.0.12 - February 04, 2014

-

-- Added BZip2 decoder.

-

-

-v 1.0.11 - February 02, 2014

-

-- Changed InputStream to work with typed_data instead of list<int>, should

-  reduce memory and increase performance.

-

-

-v 1.0.10 - January 19, 2013

-

-- Renamed InputBuffer and OutputBuffer to InputStream and OutputStream,

-  respectively.

-

-- Added readBits method to InputStream.

-

diff --git a/pub/archive/bin/tar.dart b/pub/archive/bin/tar.dart
index 2068d35..d18f73c 100755
--- a/pub/archive/bin/tar.dart
+++ b/pub/archive/bin/tar.dart
@@ -5,6 +5,7 @@
 

 import 'package:args/args.dart';

 import 'package:archive/archive.dart';

+import 'package:archive/archive_io.dart';

 

 // tar --list <file>

 // tar --extract <file> <dest>

@@ -54,7 +55,9 @@
   }

 

   TarDecoder tarArchive = new TarDecoder();

-  tarArchive.decodeBytes(data);

+  // Tell the decoder not to store the actual file data since we don't need

+  // it.

+  tarArchive.decodeBytes(data, storeData: false);

 

   print('${tarArchive.files.length} file(s)');

   tarArchive.files.forEach((f) => print('  ${f}'));

@@ -64,7 +67,46 @@
  * Extract the entries in the given tar file to a directory.

  */

 io.Directory extractFiles(String inputPath, String outputPath) {

-  io.File inputFile = new io.File(inputPath);

+  io.Directory temp_dir;

+  String tar_path = inputPath;

+

+  if (inputPath.endsWith('tar.gz') || inputPath.endsWith('tgz')) {

+    temp_dir = io.Directory.systemTemp.createTempSync('dart_archive');

+    tar_path = '${temp_dir.path}${io.Platform.pathSeparator}temp.tar';

+    InputFileStream input = new InputFileStream(inputPath);

+    OutputFileStream output = new OutputFileStream(tar_path);

+    new GZipDecoder().decodeStream(input, output);

+    input.close();

+    output.close();

+  }

+

+  io.Directory outDir = new io.Directory(outputPath);

+  if (!outDir.existsSync()) {

+    outDir.createSync(recursive: true);

+  }

+

+  InputFileStream input = new InputFileStream(tar_path);

+

+  TarDecoder tarArchive = new TarDecoder()..decodeBuffer(input);

+

+  for (TarFile file in tarArchive.files) {

+    if (!file.isFile) {

+      continue;

+    }

+    io.File f = new io.File(

+        '${outputPath}${io.Platform.pathSeparator}${file.filename}');

+    f.parent.createSync(recursive: true);

+    f.writeAsBytesSync(file.content);

+    print('  extracted ${file.filename}');

+  };

+

+  input.close();

+

+  if (temp_dir != null) {

+    temp_dir.delete(recursive: true);

+  }

+

+  /*io.File inputFile = new io.File(inputPath);

   if (!inputFile.existsSync()) fail('${inputPath} does not exist');

 

   io.Directory outDir = new io.Directory(outputPath);

@@ -80,7 +122,7 @@
   }

 

   TarDecoder tarArchive = new TarDecoder();

-  tarArchive.decodeBytes(data);

+  tarArchive.decodeBytes(data);*

 

   print('extracting to ${outDir.path}${io.Platform.pathSeparator}...');

 

@@ -93,44 +135,18 @@
     f.parent.createSync(recursive: true);

     f.writeAsBytesSync(file.content);

     print('  extracted ${file.filename}');

-  };

+  };*/

 

   return outDir;

 }

 

-io.File createTarFile(String dirPath) {

+void createTarFile(String dirPath) {

   io.Directory dir = new io.Directory(dirPath);

   if (!dir.existsSync()) fail('${dirPath} does not exist');

 

-  io.File outFile = new io.File('${dirPath}.tar.gz');

-  print('creating ${outFile.path}...');

-

-  Archive archive = new Archive();

-

-  for (io.FileSystemEntity entity in dir.listSync(recursive: true, followLinks: false)) {

-    if (entity is io.File) {

-      String name = entity.path;

-      if (name.startsWith(dir.path)) {

-        name = name.substring(dir.path.length);

-      }

-      if (name.startsWith(io.Platform.pathSeparator)) {

-        name = name.substring(io.Platform.pathSeparator.length);

-      }

-      ArchiveFile file = new ArchiveFile(name, entity.lengthSync(),

-                                         entity.readAsBytesSync());

-      file.lastModTime = entity.lastModifiedSync().millisecondsSinceEpoch;

-      file.mode = entity.statSync().mode;

-      print('  added ${name}');

-      archive.addFile(file);

-    }

-  }

-

-  List<int> data = new TarEncoder().encode(archive);

-  data = new GZipEncoder().encode(data);

-

-  outFile.writeAsBytesSync(data);

-

-  return outFile;

+  // Encode a directory from disk to disk, no memory

+  TarFileEncoder encoder = new TarFileEncoder();

+  encoder.tarDirectory(dir, compression: TarFileEncoder.GZIP);

 }

 

 void fail(String message) {

diff --git a/pub/archive/lib/archive_io.dart b/pub/archive/lib/archive_io.dart
new file mode 100755
index 0000000..47a2d93
--- /dev/null
+++ b/pub/archive/lib/archive_io.dart
@@ -0,0 +1,10 @@
+library archive_io;

+

+import 'package:archive/archive.dart';

+import 'package:path/path.dart' as path;

+import 'dart:typed_data';

+import 'dart:io' as io;

+

+part 'src/io/input_file_stream.dart';

+part 'src/io/output_file_stream.dart';

+part 'src/io/tar_file_encoder.dart';

diff --git a/pub/archive/lib/src/archive_file.dart b/pub/archive/lib/src/archive_file.dart
index bd537bf..9d8eebe 100755
--- a/pub/archive/lib/src/archive_file.dart
+++ b/pub/archive/lib/src/archive_file.dart
@@ -45,10 +45,17 @@
     }

   }

 

+  ArchiveFile.stream(this.name, this.size, content_stream) {

+    compress = false;

+    _content = content_stream;

+    //_rawContent = content_stream;

+    _compressionType = STORE;

+  }

+

   /**

    * Get the content of the file, decompressing on demand as necessary.

    */

-  List<int> get content {

+  dynamic get content {

     if (_content == null) {

       decompress();

     }

@@ -59,7 +66,7 @@
    * If the file data is compressed, decompress it.

    */

   void decompress() {

-    if (_content == null) {

+    if (_content == null && _rawContent != null) {

       if (_compressionType == DEFLATE) {

         _content = new Inflate.buffer(_rawContent, size).getBytes();

       } else {

@@ -88,5 +95,5 @@
 

   int _compressionType;

   InputStream _rawContent;

-  List<int> _content;

+  dynamic _content;

 }

diff --git a/pub/archive/lib/src/gzip_decoder.dart b/pub/archive/lib/src/gzip_decoder.dart
index 579d22d..bce2bf8 100755
--- a/pub/archive/lib/src/gzip_decoder.dart
+++ b/pub/archive/lib/src/gzip_decoder.dart
@@ -16,7 +16,34 @@
     return decodeBuffer(new InputStream(data), verify: verify);

   }

 

-  List<int> decodeBuffer(InputStream input, {bool verify: false}) {

+  void decodeStream(dynamic input, dynamic output) {

+    _readHeader(input);

+    new Inflate.stream(input, output);

+  }

+

+  List<int> decodeBuffer(dynamic input, {bool verify: false}) {

+    _readHeader(input);

+

+    // Inflate

+    List<int> buffer = new Inflate.buffer(input).getBytes();

+

+    if (verify) {

+      int crc = input.readUint32();

+      int computedCrc = getCrc32(buffer);

+      if (crc != computedCrc) {

+        throw new ArchiveException('Invalid CRC checksum');

+      }

+

+      int size = input.readUint32();

+      if (size != buffer.length) {

+        throw new ArchiveException('Size of decompressed file not correct');

+      }

+    }

+

+    return buffer;

+  }

+

+  void _readHeader(dynamic input) {

     // The GZip format has the following structure:

     // Offset   Length   Contents

     // 0      2 bytes  magic header  0x1f, 0x8b (\037 \213)

@@ -90,24 +117,5 @@
     if (flags & FLAG_HCRC != 0) {

       input.readUint16();

     }

-

-    // Inflate

-    List<int> buffer = new Inflate.buffer(input).getBytes();

-

-

-    if (verify) {

-      int crc = input.readUint32();

-      int computedCrc = getCrc32(buffer);

-      if (crc != computedCrc) {

-        throw new ArchiveException('Invalid CRC checksum');

-      }

-

-      int size = input.readUint32();

-      if (size != buffer.length) {

-        throw new ArchiveException('Size of decompressed file not correct');

-      }

-    }

-

-    return buffer;

   }

 }

diff --git a/pub/archive/lib/src/gzip_encoder.dart b/pub/archive/lib/src/gzip_encoder.dart
index f769c6d..8207ef4 100755
--- a/pub/archive/lib/src/gzip_encoder.dart
+++ b/pub/archive/lib/src/gzip_encoder.dart
@@ -26,8 +26,8 @@
   static const int OS_ACORN_RISCOS = 13;

   static const int OS_UNKNOWN = 255;

 

-  List<int> encode(List<int> data, {int level}) {

-    OutputStream output = new OutputStream();

+  List<int> encode(data, {int level, dynamic output}) {

+    dynamic output_stream = output != null ? output : new OutputStream();

 

     // The GZip format has the following structure:

     // Offset   Length   Contents

@@ -70,27 +70,41 @@
     //        4 bytes  crc32

     //        4 bytes  uncompressed input size modulo 2^32

 

-    output.writeUint16(SIGNATURE);

-    output.writeByte(DEFLATE);

+    output_stream.writeUint16(SIGNATURE);

+    output_stream.writeByte(DEFLATE);

 

     int flags = 0;

     int fileModTime = new DateTime.now().millisecondsSinceEpoch ~/ 1000;

     int extraFlags = 0;

     int osType = OS_UNKNOWN;

 

-    output.writeByte(flags);

-    output.writeUint32(fileModTime);

-    output.writeByte(extraFlags);

-    output.writeByte(osType);

+    output_stream.writeByte(flags);

+    output_stream.writeUint32(fileModTime);

+    output_stream.writeByte(extraFlags);

+    output_stream.writeByte(osType);

 

-    List<int> compressed = new Deflate(data, level: level).getBytes();

-    output.writeBytes(compressed);

+    Deflate deflate;

+    if (data is List<int>) {

+      deflate = new Deflate(data, level: level, output: output_stream);

+    } else {

+      deflate = new Deflate.buffer(data, level: level, output: output_stream);

+    }

 

-    int crc = getCrc32(data);

-    output.writeUint32(crc);

+    if (output_stream is OutputStream) {

+      List<int> compressed = deflate.getBytes();

+      output_stream.writeBytes(compressed);

+    } else {

+      deflate.finish();

+    }

 

-    output.writeUint32(data.length);

+    output_stream.writeUint32(deflate.crc32);

 

-    return output.getBytes();

+    output_stream.writeUint32(data.length);

+

+    if (output_stream is OutputStream) {

+      return output_stream.getBytes();

+    } else {

+      return null;

+    }

   }

 }

diff --git a/pub/archive/lib/src/io/input_file_stream.dart b/pub/archive/lib/src/io/input_file_stream.dart
new file mode 100755
index 0000000..707c77b
--- /dev/null
+++ b/pub/archive/lib/src/io/input_file_stream.dart
@@ -0,0 +1,315 @@
+part of archive_io;

+

+class InputFileStream {

+  String path;

+  io.RandomAccessFile _file;

+  final int byteOrder;

+  int _fileSize = 0;

+  int _filePosition = 0;

+  List<int> _buffer;

+  int _bufferSize = 0;

+  int _bufferPosition = 0;

+  int _maxBufferSize;

+  static const int _kDefaultBufferSize = 4096;

+

+  InputFileStream(this.path, {this.byteOrder: LITTLE_ENDIAN,

+    int bufferSize: _kDefaultBufferSize}) {

+    _maxBufferSize = bufferSize;

+    _buffer = new Uint8List(_maxBufferSize);

+    _file = new io.File(path).openSync();

+    _fileSize = _file.lengthSync();

+

+    _readBuffer();

+  }

+

+  InputFileStream.file(io.File file, {this.byteOrder: LITTLE_ENDIAN,

+    int bufferSize: _kDefaultBufferSize}) {

+    _maxBufferSize = bufferSize;

+    _buffer = new Uint8List(_maxBufferSize);

+    _file = file.openSync();

+    _fileSize = _file.lengthSync();

+    _readBuffer();

+  }

+

+  void close() {

+    _file.closeSync();

+    _fileSize = 0;

+  }

+

+  int get length => _fileSize;

+

+  int get position => _filePosition;

+

+  bool get isEOS => (_filePosition >= _fileSize) &&

+      (_bufferPosition >= _bufferSize);

+

+  int get bufferSize => _bufferSize;

+

+  int get bufferPosition => _bufferPosition;

+

+  int get bufferRemaining => _bufferSize - _bufferPosition;

+

+  int get fileRemaining => _fileSize - _filePosition;

+

+  void reset() {

+    _filePosition = 0;

+    _file.setPositionSync(0);

+    _readBuffer();

+  }

+

+  void skip(int length) {

+    if ((_bufferPosition + length) < _bufferSize) {

+      _bufferPosition += length;

+    } else {

+      int remaining = length - (_bufferSize - _bufferPosition);

+      while (!isEOS) {

+        _readBuffer();

+        if (remaining < _bufferSize) {

+          _bufferPosition += remaining;

+          break;

+        }

+        remaining -= _bufferSize;

+      }

+    }

+  }

+

+  /**

+   * Read [count] bytes from an [offset] of the current read position, without

+   * moving the read position.

+   */

+  InputStream peekBytes(int count, [int offset = 0]) {

+    int end = _bufferPosition + offset + count;

+    if (end > 0 && end < _bufferSize) {

+      List<int> bytes = _buffer.sublist(_bufferPosition + offset, end);

+      return new InputStream(bytes);

+    }

+

+    Uint8List bytes = new Uint8List(count);

+

+    int remaining = _bufferSize - (_bufferPosition + offset);

+    if (remaining > 0) {

+      List<int> bytes1 = _buffer.sublist(_bufferPosition + offset, _bufferSize);

+      bytes.setRange(0, remaining, bytes1);

+    }

+

+    _file.readIntoSync(bytes, remaining, count);

+    _file.setPositionSync(_filePosition);

+

+    return new InputStream(bytes);

+  }

+

+  void rewind(int count) {

+    if (_bufferPosition - count < 0) {

+      int remaining = (_bufferPosition - count).abs();

+      _filePosition = _filePosition - _bufferSize - remaining;

+      if (_filePosition < 0) {

+        _filePosition = 0;

+      }

+      _file.setPositionSync(_filePosition);

+      _readBuffer();

+      return;

+    }

+    _bufferPosition -= count;

+  }

+

+  int readByte() {

+    if (isEOS) {

+      return 0;

+    }

+    if (_bufferPosition >= _bufferSize) {

+      _readBuffer();

+    }

+    if (_bufferPosition >= _bufferSize) {

+      return 0;

+    }

+    return _buffer[_bufferPosition++] & 0xff;

+  }

+

+  /**

+   * Read a 16-bit word from the stream.

+   */

+  int readUint16() {

+    int b1 = 0;

+    int b2 = 0;

+    if ((_bufferPosition + 2) < _bufferSize) {

+      b1 = _buffer[_bufferPosition++] & 0xff;

+      b2 = _buffer[_bufferPosition++] & 0xff;

+    } else {

+      b1 = readByte();

+      b2 = readByte();

+    }

+    if (byteOrder == BIG_ENDIAN) {

+      return (b1 << 8) | b2;

+    }

+    return (b2 << 8) | b1;

+  }

+

+  /**

+   * Read a 24-bit word from the stream.

+   */

+  int readUint24() {

+    int b1 = 0;

+    int b2 = 0;

+    int b3 = 0;

+    if ((_bufferPosition + 3) < _bufferSize) {

+      b1 = _buffer[_bufferPosition++] & 0xff;

+      b2 = _buffer[_bufferPosition++] & 0xff;

+      b3 = _buffer[_bufferPosition++] & 0xff;

+    } else {

+      b1 = readByte();

+      b2 = readByte();

+      b3 = readByte();

+    }

+

+    if (byteOrder == BIG_ENDIAN) {

+      return b3 | (b2 << 8) | (b1 << 16);

+    }

+    return b1 | (b2 << 8) | (b3 << 16);

+  }

+

+  /**

+   * Read a 32-bit word from the stream.

+   */

+  int readUint32() {

+    int b1 = 0;

+    int b2 = 0;

+    int b3 = 0;

+    int b4 = 0;

+    if ((_bufferPosition + 4) < _bufferSize) {

+      b1 = _buffer[_bufferPosition++] & 0xff;

+      b2 = _buffer[_bufferPosition++] & 0xff;

+      b3 = _buffer[_bufferPosition++] & 0xff;

+      b4 = _buffer[_bufferPosition++] & 0xff;

+    } else {

+      b1 = readByte();

+      b2 = readByte();

+      b3 = readByte();

+      b4 = readByte();

+    }

+

+    if (byteOrder == BIG_ENDIAN) {

+      return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;

+    }

+    return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;

+  }

+

+  /**

+   * Read a 64-bit word form the stream.

+   */

+  int readUint64() {

+    int b1 = 0;

+    int b2 = 0;

+    int b3 = 0;

+    int b4 = 0;

+    int b5 = 0;

+    int b6 = 0;

+    int b7 = 0;

+    int b8 = 0;

+    if ((_bufferPosition + 8) < _bufferSize) {

+      b1 = _buffer[_bufferPosition++] & 0xff;

+      b2 = _buffer[_bufferPosition++] & 0xff;

+      b3 = _buffer[_bufferPosition++] & 0xff;

+      b4 = _buffer[_bufferPosition++] & 0xff;

+      b5 = _buffer[_bufferPosition++] & 0xff;

+      b6 = _buffer[_bufferPosition++] & 0xff;

+      b7 = _buffer[_bufferPosition++] & 0xff;

+      b8 = _buffer[_bufferPosition++] & 0xff;

+    } else {

+      b1 = readByte();

+      b2 = readByte();

+      b3 = readByte();

+      b4 = readByte();

+      b5 = readByte();

+      b6 = readByte();

+      b7 = readByte();

+      b8 = readByte();

+    }

+

+    if (byteOrder == BIG_ENDIAN) {

+      return (b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) |

+      (b5 << 24) | (b6 << 16) | (b7 << 8) | b8;

+    }

+    return (b8 << 56) | (b7 << 48) | (b6 << 40) | (b5 << 32) |

+    (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;

+  }

+

+  InputStream readBytes(int length) {

+    if (isEOS) {

+      return null;

+    }

+

+    if (_bufferPosition == _bufferSize) {

+      _readBuffer();

+    }

+

+    if (_remainingBufferSize >= length) {

+      List<int> bytes = _buffer.sublist(_bufferPosition,

+          _bufferPosition + length);

+      _bufferPosition += length;

+      return new InputStream(bytes);

+    }

+

+    int total_remaining = fileRemaining + _remainingBufferSize;

+    if (length > total_remaining) {

+      length = total_remaining;

+    }

+

+    Uint8List bytes = new Uint8List(length);

+

+    int offset = 0;

+    while (length > 0) {

+      int remaining = _bufferSize - _bufferPosition;

+      int end = (length > remaining) ? _bufferSize : (_bufferPosition + length);

+      List<int> l = _buffer.sublist(_bufferPosition, end);

+      // TODO probably better to use bytes.setRange here.

+      for (int i = 0; i < l.length; ++i) {

+        bytes[offset + i] = l[i];

+      }

+      offset += l.length;

+      length -= l.length;

+      _bufferPosition = end;

+      if (length > 0 && _bufferPosition == _bufferSize) {

+        _readBuffer();

+        if (_bufferSize == 0) {

+          break;

+        }

+      }

+    }

+

+    return new InputStream(bytes);

+  }

+

+  /**

+   * Read a null-terminated string, or if [len] is provided, that number of

+   * bytes returned as a string.

+   */

+  String readString([int len]) {

+    if (len == null) {

+      List<int> codes = [];

+      while (!isEOS) {

+        int c = readByte();

+        if (c == 0) {

+          return new String.fromCharCodes(codes);

+        }

+        codes.add(c);

+      }

+      throw new ArchiveException('EOF reached without finding string terminator');

+    }

+

+    InputStream s = readBytes(len);

+    Uint8List bytes = s.toUint8List();

+    String str = new String.fromCharCodes(bytes);

+    return str;

+  }

+

+  int get _remainingBufferSize => _bufferSize - _bufferPosition;

+

+  void _readBuffer() {

+    _bufferPosition = 0;

+    _bufferSize = _file.readIntoSync(_buffer);

+    if (_bufferSize == 0) {

+      return;

+    }

+    _filePosition += _bufferSize;

+  }

+}

diff --git a/pub/archive/lib/src/io/output_file_stream.dart b/pub/archive/lib/src/io/output_file_stream.dart
new file mode 100755
index 0000000..2e25b4a
--- /dev/null
+++ b/pub/archive/lib/src/io/output_file_stream.dart
@@ -0,0 +1,101 @@
+part of archive_io;

+

+class OutputFileStream {

+  String path;

+  final int byteOrder;

+  int length;

+  io.File _file;

+  io.RandomAccessFile _fp;

+

+  OutputFileStream(this.path, {this.byteOrder: LITTLE_ENDIAN})

+    : length = 0 {

+    _file = new io.File(path);

+    _fp = _file.openSync(mode: io.FileMode.WRITE);

+  }

+

+  void close() {

+    _fp.closeSync();

+    _file = null;

+  }

+

+  /**

+   * Write a byte to the end of the buffer.

+   */

+  void writeByte(int value) {

+    _fp.writeByteSync(value);

+    length++;

+  }

+

+  /**

+   * Write a set of bytes to the end of the buffer.

+   */

+  void writeBytes(bytes, [int len]) {

+    if (len == null) {

+      len = bytes.length;

+    }

+    if (bytes is InputFileStream) {

+      InputFileStream in_stream = bytes as InputFileStream;

+      while (!in_stream.isEOS) {

+        int len = in_stream.bufferRemaining;

+        InputStream data = in_stream.readBytes(len);

+        writeInputStream(data);

+      }

+    } else {

+      _fp.writeFromSync(bytes, 0, len);

+    }

+    length += len;

+  }

+

+  void writeInputStream(InputStream bytes) {

+    _fp.writeFromSync(bytes.buffer, bytes.offset, bytes.length);

+  }

+

+  /**

+   * Write a 16-bit word to the end of the buffer.

+   */

+  void writeUint16(int value) {

+    if (byteOrder == BIG_ENDIAN) {

+      writeByte((value >> 8) & 0xff);

+      writeByte((value) & 0xff);

+      return;

+    }

+    writeByte((value) & 0xff);

+    writeByte((value >> 8) & 0xff);

+  }

+

+  /**

+   * Write a 32-bit word to the end of the buffer.

+   */

+  void writeUint32(int value) {

+    if (byteOrder == BIG_ENDIAN) {

+      writeByte((value >> 24) & 0xff);

+      writeByte((value >> 16) & 0xff);

+      writeByte((value >> 8) & 0xff);

+      writeByte((value) & 0xff);

+      return;

+    }

+    writeByte((value) & 0xff);

+    writeByte((value >> 8) & 0xff);

+    writeByte((value >> 16) & 0xff);

+    writeByte((value >> 24) & 0xff);

+  }

+

+  List<int> subset(int start, [int end]) {

+    int pos = _fp.positionSync();

+    if (start < 0) {

+      start = pos + start;

+    }

+    int length = 0;

+    if (end == null) {

+      end = pos;

+    } else if (end < 0) {

+      end = pos + end;

+    }

+    length = (end - start);

+    _fp.setPositionSync(start);

+    Uint8List buffer = new Uint8List(length);

+    _fp.readIntoSync(buffer);

+    _fp.setPositionSync(pos);

+    return buffer;

+  }

+}
\ No newline at end of file
diff --git a/pub/archive/lib/src/io/tar_file_encoder.dart b/pub/archive/lib/src/io/tar_file_encoder.dart
new file mode 100755
index 0000000..7d6daa4
--- /dev/null
+++ b/pub/archive/lib/src/io/tar_file_encoder.dart
@@ -0,0 +1,73 @@
+part of archive_io;

+

+

+class TarFileEncoder {

+  String tar_path;

+  OutputFileStream _output;

+  TarEncoder _encoder;

+

+  static const int STORE = 0;

+  static const int GZIP = 1;

+

+  void tarDirectory(io.Directory dir, {int compression: STORE,

+                    String filename}) {

+    String dirPath = dir.path;

+    String tar_path = filename != null ? filename : '${dirPath}.tar';

+    String tgz_path = filename != null ? filename : '${dirPath}.tar.gz';

+

+    io.Directory temp_dir;

+    if (compression == GZIP) {

+      temp_dir = io.Directory.systemTemp.createTempSync('dart_archive');

+      tar_path = temp_dir.path + '/temp.tar';

+    }

+

+    // Encode a directory from disk to disk, no memory

+    open(tar_path);

+    addDirectory(new io.Directory(dirPath));

+    close();

+

+    if (compression == GZIP) {

+      InputFileStream input = new InputFileStream(tar_path);

+      OutputFileStream output = new OutputFileStream(tgz_path);

+      new GZipEncoder()..encode(input, output: output);

+      input.close();

+      new io.File(input.path).deleteSync();

+    }

+  }

+

+  void open(String tar_path) {

+    this.tar_path = tar_path;

+    _output = new OutputFileStream(tar_path);

+    _encoder = new TarEncoder();

+    _encoder.start(_output);

+  }

+

+  void addDirectory(io.Directory dir) {

+    List files = dir.listSync(recursive:true);

+

+    for (var fe in files) {

+      if (fe is! io.File) {

+        continue;

+      }

+

+      io.File f = fe as io.File;

+      String rel_path = path.relative(f.path, from: dir.path);

+      addFile(f, rel_path);

+    }

+  }

+

+  void addFile(io.File file, [String filename]) {

+    InputFileStream file_stream = new InputFileStream.file(file);

+    ArchiveFile f = new ArchiveFile.stream(filename == null ? file.path : filename,

+        file.lengthSync(), file_stream);

+    f.lastModTime = file.lastModifiedSync().millisecondsSinceEpoch;

+    f.mode = file.statSync().mode;

+    _encoder.add(f);

+    file_stream.close();

+  }

+

+  void close() {

+    _encoder.finish();

+    _output.close();

+  }

+}
\ No newline at end of file
diff --git a/pub/archive/lib/src/tar/tar_file.dart b/pub/archive/lib/src/tar/tar_file.dart
index ba10b51..168d7d7 100755
--- a/pub/archive/lib/src/tar/tar_file.dart
+++ b/pub/archive/lib/src/tar/tar_file.dart
@@ -59,12 +59,12 @@
   int deviceMinorNumber = 0; // 8 bytes

   String filenamePrefix = ''; // 155 bytes

   InputStream _rawContent;

-  List<int> _content;

+  dynamic _content;

 

   TarFile() {

   }

 

-  TarFile.read(InputStream input) {

+  TarFile.read(dynamic input, {bool storeData: true}) {

     InputStream header = input.readBytes(512);

 

     // The name, linkname, magic, uname, and gname are null-terminated

@@ -90,7 +90,11 @@
       deviceMinorNumber = _parseInt(header, 8);

     }

 

-    _rawContent = input.readBytes(fileSize);

+    if (storeData) {

+      _rawContent = input.readBytes(fileSize);

+    } else {

+      input.skip(fileSize);

+    }

 

     if (isFile && fileSize > 0) {

       int remainder = fileSize % 512;

@@ -117,7 +121,7 @@
 

   String toString() => '[${filename}, ${mode}, ${fileSize}]';

 

-  void write(OutputStream output) {

+  void write(dynamic output) {

     fileSize = size;

 

     // The name, linkname, magic, uname, and gname are null-terminated

@@ -160,7 +164,6 @@
     headerBytes[154] = 0;

     headerBytes[155] = 32;

 

-

     output.writeBytes(header.getBytes());

 

     if (_content != null) {

@@ -170,7 +173,7 @@
     }

 

     if (isFile && fileSize > 0) {

-      // Padd to 512-byte boundary

+      // Pad to 512-byte boundary

       int remainder = fileSize % 512;

       if (remainder != 0) {

         int skiplen = 512 - remainder;

diff --git a/pub/archive/lib/src/tar_decoder.dart b/pub/archive/lib/src/tar_decoder.dart
index feb6515..d42050f 100755
--- a/pub/archive/lib/src/tar_decoder.dart
+++ b/pub/archive/lib/src/tar_decoder.dart
@@ -6,22 +6,26 @@
 class TarDecoder {

   List<TarFile> files = [];

 

-  Archive decodeBytes(List<int> data, {bool verify: false}) {

-    return decodeBuffer(new InputStream(data), verify: verify);

+  Archive decodeBytes(List<int> data, {bool verify: false,

+      bool storeData: true}) {

+    return decodeBuffer(new InputStream(data), verify: verify,

+        storeData: storeData);

   }

 

-  Archive decodeBuffer(InputStream input, {bool verify: false}) {

+  Archive decodeBuffer(dynamic input, {bool verify: false,

+      bool storeData: true}) {

     Archive archive = new Archive();

     files.clear();

 

     //TarFile paxHeader = null;

     while (!input.isEOS) {

       // End of archive when two consecutive 0's are found.

-      if (input[0] == 0 && input[1] == 0) {

+      InputStream end_check = input.peekBytes(2);

+      if (end_check.length < 2 || (end_check[0] == 0 && end_check[1] == 0)) {

         break;

       }

 

-      TarFile tf = new TarFile.read(input);

+      TarFile tf = new TarFile.read(input, storeData: storeData);

       // In POSIX formatted tar files, a separate 'PAX' file contains extended

       // metadata for files. These are identified by having a type flag 'X'.

       // TODO parse these metadata values.

diff --git a/pub/archive/lib/src/tar_encoder.dart b/pub/archive/lib/src/tar_encoder.dart
index 9ec75b8..fd319ef 100755
--- a/pub/archive/lib/src/tar_encoder.dart
+++ b/pub/archive/lib/src/tar_encoder.dart
@@ -5,25 +5,44 @@
  */

 class TarEncoder {

   List<int> encode(Archive archive) {

-    OutputStream output = new OutputStream();

+    OutputStream output_stream = new OutputStream();

+    start(output_stream);

 

     for (ArchiveFile file in archive.files) {

-      TarFile ts = new TarFile();

-      ts.filename = file.name;

-      ts.fileSize = file.size;

-      ts.mode = file.mode;

-      ts.ownerId = file.ownerId;

-      ts.groupId = file.groupId;

-      ts.lastModTime = file.lastModTime;

-      ts._content = file.content;

-      ts.write(output);

+      add(file);

     }

 

+    finish();

+

+    return output_stream.getBytes();

+  }

+

+  void start([dynamic output_stream]) {

+    _output_stream = output_stream != null ? output_stream : new OutputStream();

+  }

+

+  void add(ArchiveFile file) {

+    if (_output_stream == null) {

+      return;

+    }

+    TarFile ts = new TarFile();

+    ts.filename = file.name;

+    ts.fileSize = file.size;

+    ts.mode = file.mode;

+    ts.ownerId = file.ownerId;

+    ts.groupId = file.groupId;

+    ts.lastModTime = file.lastModTime;

+    ts._content = file.content;

+    ts.write(_output_stream);

+  }

+

+  void finish() {

     // At the end of the archive file there are two 512-byte blocks filled

     // with binary zeros as an end-of-file marker.

     Uint8List eof = new Uint8List(1024);

-    output.writeBytes(eof);

-

-    return output.getBytes();

+    _output_stream.writeBytes(eof);

+    _output_stream = null;

   }

+

+  dynamic _output_stream;

 }

diff --git a/pub/archive/lib/src/util/input_stream.dart b/pub/archive/lib/src/util/input_stream.dart
index 29c0ae0..0efe4d5 100755
--- a/pub/archive/lib/src/util/input_stream.dart
+++ b/pub/archive/lib/src/util/input_stream.dart
@@ -14,7 +14,8 @@
    */

   InputStream(data, {this.byteOrder: LITTLE_ENDIAN, int start: 0,

               int length}) :

-    this.buffer = data is ByteData ? new Uint8List.view(data.buffer) : data as List<int>,

+    this.buffer = data is ByteData ? new Uint8List.view(data.buffer) :

+        data as List<int>,

     this.start = start {

     _length = length == null ? buffer.length : length;

     offset = start;

@@ -53,6 +54,16 @@
   }

 

   /**

+   * Rewind the read head of the stream by the given number of bytes.

+   */

+  void rewind([int length = 1]) {

+    offset -= length;

+    if (offset < 0) {

+      offset = 0;

+    }

+  }

+

+  /**

    * Access the buffer relative from the current position.

    */

   int operator[](int index) => buffer[offset + index];

@@ -212,10 +223,17 @@
     int len = length;

     if (buffer is Uint8List) {

       Uint8List b = buffer;

+      if ((offset + len) > b.length) {

+        len = b.length - offset;

+      }

       Uint8List bytes = new Uint8List.view(b.buffer, offset, len);

       return bytes;

     }

-    return new Uint8List.fromList(buffer.sublist(offset, offset + len));

+    int end = offset + len;

+    if (end > buffer.length) {

+      end = buffer.length;

+    }

+    return new Uint8List.fromList(buffer.sublist(offset, end));

   }

 

   int _length;

diff --git a/pub/archive/lib/src/util/output_stream.dart b/pub/archive/lib/src/util/output_stream.dart
index 37aada6..91fd8af 100755
--- a/pub/archive/lib/src/util/output_stream.dart
+++ b/pub/archive/lib/src/util/output_stream.dart
@@ -26,7 +26,6 @@
     length = 0;

   }

 

-

   /**

    * Reset the buffer.

    */

@@ -34,7 +33,6 @@
     length = 0;

   }

 

-

   /**

    * Write a byte to the end of the buffer.

    */

@@ -45,7 +43,6 @@
     _buffer[length++] = value & 0xff;

   }

 

-

   /**

    * Write a set of bytes to the end of the buffer.

    */

@@ -60,7 +57,6 @@
     length += len;

   }

 

-

   void writeInputStream(InputStream bytes) {

     while (length + bytes.length > _buffer.length) {

       _expandBuffer((length + bytes.length) - _buffer.length);

@@ -69,7 +65,6 @@
     length += bytes.length;

   }

 

-

   /**

    * Write a 16-bit word to the end of the buffer.

    */

@@ -83,7 +78,6 @@
     writeByte((value >> 8) & 0xff);

   }

 

-

   /**

    * Write a 32-bit word to the end of the buffer.

    */

@@ -101,7 +95,6 @@
     writeByte((value >> 24) & 0xff);

   }

 

-

   /**

    * Return the subset of the buffer in the range [start:end].

    * If [start] or [end] are < 0 then it is relative to the end of the buffer.

@@ -122,7 +115,6 @@
     return new Uint8List.view(_buffer.buffer, start, end - start);

   }

 

-

   /**

    * Grow the buffer to accommodate additional data.

    */

@@ -139,7 +131,6 @@
     _buffer = newBuffer;

   }

 

-

   static const int _BLOCK_SIZE = 0x8000; // 32k block-size

   Uint8List _buffer;

 }

diff --git a/pub/archive/lib/src/zlib/deflate.dart b/pub/archive/lib/src/zlib/deflate.dart
index 7e2025b..8e5e8ed 100755
--- a/pub/archive/lib/src/zlib/deflate.dart
+++ b/pub/archive/lib/src/zlib/deflate.dart
@@ -15,19 +15,29 @@
   static const int FULL_FLUSH = 3;

   static const int FINISH = 4;

 

+  int crc32;

+

   Deflate(List<int> bytes, {int level: DEFAULT_COMPRESSION,

-           int flush: FINISH}) :

-    _input = new InputStream(bytes) {

+           int flush: FINISH, dynamic output})

+    : _input = new InputStream(bytes),

+      _output = output != null ? output : new OutputStream() {

+    crc32 = 0;

     _init(level);

     _deflate(flush);

   }

 

   Deflate.buffer(this._input, {int level: DEFAULT_COMPRESSION,

-                  int flush: FINISH}) {

+                  int flush: FINISH, dynamic output})

+    : _output = output != null ? output : new OutputStream() {

+    crc32 = 0;

     _init(level);

     _deflate(flush);

   }

 

+  void finish() {

+    _flushPending();

+  }

+

   /**

    * Get the resulting compressed bytes.

    */

@@ -127,6 +137,8 @@
 

     _lastFlush = NO_FLUSH;

 

+    crc32 = 0;

+

     _trInit();

     _lmInit();

   }

@@ -1214,19 +1226,25 @@
    * allocating a large strm->next_in buffer and copying from it.

    * (See also flush_pending()).

    */

+  int total = 0;

   int _readBuf(Uint8List buf, int start, int size) {

-    int len = _input.length;

-

-    if (len > size) {

-      len = size;

+    if (size == 0 || _input.isEOS) {

+      return 0;

     }

 

+    InputStream data = _input.readBytes(size);

+    int len = data.length;

     if (len == 0) {

       return 0;

     }

 

-    InputStream bytes = _input.readBytes(len);

-    buf.setRange(start, start + len, bytes.toUint8List());

+    Uint8List bytes = data.toUint8List();

+    if (len > bytes.length) {

+      len = bytes.length;

+    }

+    buf.setRange(start, start + len, bytes);

+    total += len;

+    crc32 = getCrc32(bytes, crc32);

 

     return len;

   }

@@ -1238,7 +1256,6 @@
    */

   void _flushPending() {

     int len = _pending;

-

     _output.writeBytes(_pendingBuffer, len);

 

     _pendingOut += len;

@@ -1346,8 +1363,8 @@
 

   static const int END_BLOCK = 256;

 

-  InputStream _input;

-  OutputStream _output = new OutputStream();

+  dynamic _input;

+  dynamic _output;

 

   int _status;

   /// output still pending

diff --git a/pub/archive/lib/src/zlib/inflate.dart b/pub/archive/lib/src/zlib/inflate.dart
index c481e94..4c865f0 100755
--- a/pub/archive/lib/src/zlib/inflate.dart
+++ b/pub/archive/lib/src/zlib/inflate.dart
@@ -1,8 +1,8 @@
 part of archive;

 

 class Inflate {

-  InputStream input;

-  final OutputStream output;

+  dynamic input;

+  final dynamic output;

 

   Inflate(List<int> bytes, [int uncompressedSize]) :

     input = new InputStream(bytes),

@@ -10,26 +10,27 @@
     _inflate();

   }

 

-

-  Inflate.buffer(InputStream buffer, [int uncompressedSize]) :

-    input = buffer,

+  Inflate.buffer(this.input, [int uncompressedSize]) :

     output = new OutputStream(size: uncompressedSize) {

     _inflate();

   }

 

-

-  Inflate.stream([List<int> bytes]) :

-    output = new OutputStream() {

-    _bitBuffer = 0;

-    _bitBufferLen = 0;

-    if (bytes != null) {

-      input = new InputStream(bytes);

+  Inflate.stream([this.input, dynamic output_stream]) :

+    output = output_stream != null ? output_stream : new OutputStream() {

+    if (input == null || input is List<int>) {

+      _bitBuffer = 0;

+      _bitBufferLen = 0;

+      if (input != null) {

+        input = new InputStream(input);

+      }

+      return;

     }

+

+    _inflate();

   }

 

-

   void streamInput(List<int> bytes) {

-    if (input != null) {

+    if (input != null && input is InputStream) {

       input.offset = _blockPos;

     }

     int inputLen = input == null ? 0 : input.length;

@@ -45,17 +46,20 @@
     input = new InputStream(newBytes);

   }

 

-

   List<int> inflateNext() {

     _bitBuffer = 0;

     _bitBufferLen = 0;

-    output.clear();

+    if (output is OutputStream) {

+      output.clear();

+    }

     if (input == null || input.isEOS) {

       return null;

     }

 

     try {

-      _blockPos = input.offset;

+      if (input is InputStream) {

+        _blockPos = input.offset;

+      }

       _parseBlock();

       // If it didn't finish reading the block, it will have thrown an exception

       _blockPos = 0;

@@ -63,10 +67,12 @@
       return null;

     }

 

-    return output.getBytes();

+    if (output is OutputStream) {

+      return output.getBytes();

+    }

+    return null;

   }

 

-

   /**

    * Get the decompressed data.

    */

@@ -74,15 +80,18 @@
     return output.getBytes();

   }

 

-

   void _inflate() {

     _bitBuffer = 0;

     _bitBufferLen = 0;

 

-    while (_parseBlock());

+    while (!input.isEOS) {

+      bool more = _parseBlock();

+      if (!more) {

+        break;

+      }

+    }

   }

 

-

   /**

    * Parse deflated block.  Returns true if there is more to read, false

    * if we're done.

@@ -187,10 +196,10 @@
     _bitBufferLen = 0;

 

     int len = _readBits(16);

-    int nlen = _readBits(16);

+    int nlen = _readBits(16) ^ 0xffff;

 

-    // check len & nlen

-    if (len == ~nlen) {

+    // Make sure the block size checksum is valid.

+    if (len != 0 && len != nlen) {

       throw new ArchiveException('Invalid uncompressed block header');

     }

 

@@ -293,7 +302,7 @@
 

     while (_bitBufferLen >= 8) {

       _bitBufferLen -= 8;

-      input.offset--;

+      input.rewind(1);

     }

   }

 

diff --git a/pub/archive/pubspec.yaml b/pub/archive/pubspec.yaml
index fd58481..4fd6bf7 100755
--- a/pub/archive/pubspec.yaml
+++ b/pub/archive/pubspec.yaml
@@ -1,5 +1,5 @@
 name: archive

-version: 1.0.29

+version: 1.0.31

 author: Brendan Duncan <brendanduncan@gmail.com>

 description: Provides encoders and decoders for various archive and compression formats such as zip, tar, bzip2, gzip, and zlib.

 homepage: https://github.com/brendan-duncan/archive

@@ -7,8 +7,9 @@
   sdk: '>=1.0.0 <2.0.0'

 documentation: https://github.com/brendan-duncan/archive/wiki

 dependencies:

-  crypto: '>=0.9.2 <3.0.0'

+  crypto: '>=2.0.0 <3.0.0'

   args: '>=0.13.7 <1.0.0'

+  path: '>=1.4.1 <2.0.0'

 dev_dependencies:

   browser: '<1.0.0'

   test: '>=0.12.13 <1.0.0'

diff --git a/pub/collection/BUILD.gn b/pub/collection/BUILD.gn
index e39a1ab..36fd5b6 100644
--- a/pub/collection/BUILD.gn
+++ b/pub/collection/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for collection-1.14.1
+# This file is generated by importer.py for collection-1.14.2
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/collection/pubspec.yaml b/pub/collection/pubspec.yaml
index 4ba307d..07cb622 100644
--- a/pub/collection/pubspec.yaml
+++ b/pub/collection/pubspec.yaml
@@ -1,5 +1,5 @@
 name: collection
-version: 1.14.1
+version: 1.14.2
 author: Dart Team <misc@dartlang.org>
 description: Collections and utilities functions and classes related to collections.
 homepage: https://www.github.com/dart-lang/collection
diff --git a/pub/dart_style/BUILD.gn b/pub/dart_style/BUILD.gn
index c990154..5d33cf6 100644
--- a/pub/dart_style/BUILD.gn
+++ b/pub/dart_style/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for dart_style-1.0.6
+# This file is generated by importer.py for dart_style-1.0.7
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/dart_style/CHANGELOG.md b/pub/dart_style/CHANGELOG.md
index 248d1f0..4e50cfa 100644
--- a/pub/dart_style/CHANGELOG.md
+++ b/pub/dart_style/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 1.0.7
+
+* Format multiline strings as block arguments (#570).
+* Fix call to analyzer API.
+* Support assert in initializer list experimental syntax (#522).
+
 # 1.0.6
 
 * Support URIs in part-of directives (#615).
diff --git a/pub/dart_style/bin/format.dart b/pub/dart_style/bin/format.dart
index 7af4d16..a27e818 100644
--- a/pub/dart_style/bin/format.dart
+++ b/pub/dart_style/bin/format.dart
@@ -14,7 +14,7 @@
 import 'package:dart_style/src/source_code.dart';
 
 // Note: The following line of code is modified by tool/grind.dart.
-const version = "1.0.6";
+const version = "1.0.7";
 
 void main(List<String> args) {
   var parser = new ArgParser(allowTrailingOptions: true);
diff --git a/pub/dart_style/lib/src/argument_list_visitor.dart b/pub/dart_style/lib/src/argument_list_visitor.dart
index 3d0f7dc..f59dd71 100644
--- a/pub/dart_style/lib/src/argument_list_visitor.dart
+++ b/pub/dart_style/lib/src/argument_list_visitor.dart
@@ -15,8 +15,8 @@
 import 'source_visitor.dart';
 
 /// Helper class for [SourceVisitor] that handles visiting and writing an
-/// [ArgumentList], including all of the special code needed to handle function
-/// and collection arguments.
+/// [ArgumentList], including all of the special code needed to handle
+/// block-formatted arguments.
 class ArgumentListVisitor {
   final SourceVisitor _visitor;
 
@@ -47,13 +47,14 @@
   bool get _isSingle =>
       _allArguments.length == 1 && _allArguments.single is! NamedExpression;
 
-  /// Whether this argument list has any collection or block function arguments.
+  /// Whether this argument list has any arguments that should be formatted as
+  /// blocks.
   // TODO(rnystrom): Returning true based on collections is non-optimal. It
   // forces a method chain to break into two but the result collection may not
   // actually split which can lead to a method chain that's allowed to break
   // where it shouldn't.
   bool get hasBlockArguments =>
-      _arguments._collections.isNotEmpty || _functions != null;
+      _arguments._blocks.isNotEmpty || _functions != null;
 
   factory ArgumentListVisitor(SourceVisitor visitor, ArgumentList node) {
     return new ArgumentListVisitor.forArguments(
@@ -102,7 +103,7 @@
     //
     //     function(named: () {
     //       something();
-    //     }
+    //     },
     //         another: argument);
     if (functionsStart != null &&
         arguments[0] is NamedExpression &&
@@ -308,23 +309,23 @@
   /// The named arguments, in order.
   final List<Expression> _named;
 
-  /// Maps each argument that is a collection literal that get special
-  /// formatting to the token for the collection's open bracket.
-  final Map<Expression, Token> _collections;
+  /// Maps each block argument, excluding functions, to the first token for that
+  /// argument.
+  final Map<Expression, Token> _blocks;
 
-  /// The number of leading collections.
+  /// The number of leading block arguments, excluding functions.
   ///
-  /// If all arguments are collections, this counts them.
-  final int _leadingCollections;
+  /// If all arguments are blocks, this counts them.
+  final int _leadingBlocks;
 
-  /// The number of trailing collections.
+  /// The number of trailing blocks arguments.
   ///
-  /// If all arguments are collections, this is zero.
-  final int _trailingCollections;
+  /// If all arguments are blocks, this is zero.
+  final int _trailingBlocks;
 
-  /// The rule used to split the bodies of all of the collection arguments.
-  Rule get collectionRule => _collectionRule;
-  Rule _collectionRule;
+  /// The rule used to split the bodies of all block arguments.
+  Rule get blockRule => _blockRule;
+  Rule _blockRule;
 
   /// The most recent chunk that split before an argument.
   Chunk get previousSplit => _previousSplit;
@@ -337,48 +338,48 @@
         arguments.takeWhile((arg) => arg is! NamedExpression).toList();
     var named = arguments.skip(positional.length).toList();
 
-    var collections = <Expression, Token>{};
+    var blocks = <Expression, Token>{};
     for (var argument in arguments) {
-      var bracket = _getCollectionBracket(argument);
-      if (bracket != null) collections[argument] = bracket;
+      var bracket = _blockToken(argument);
+      if (bracket != null) blocks[argument] = bracket;
     }
 
-    // Count the leading arguments that are collection literals.
-    var leadingCollections = 0;
+    // Count the leading arguments that are blocks.
+    var leadingBlocks = 0;
     for (var argument in arguments) {
-      if (!collections.containsKey(argument)) break;
-      leadingCollections++;
+      if (!blocks.containsKey(argument)) break;
+      leadingBlocks++;
     }
 
-    // Count the trailing arguments that are collection literals.
-    var trailingCollections = 0;
-    if (leadingCollections != arguments.length) {
+    // Count the trailing arguments that are blocks.
+    var trailingBlocks = 0;
+    if (leadingBlocks != arguments.length) {
       for (var argument in arguments.reversed) {
-        if (!collections.containsKey(argument)) break;
-        trailingCollections++;
+        if (!blocks.containsKey(argument)) break;
+        trailingBlocks++;
       }
     }
 
-    // Collections must all be a prefix or suffix of the argument list (and not
+    // Blocks must all be a prefix or suffix of the argument list (and not
     // both).
-    if (leadingCollections != collections.length) leadingCollections = 0;
-    if (trailingCollections != collections.length) trailingCollections = 0;
+    if (leadingBlocks != blocks.length) leadingBlocks = 0;
+    if (trailingBlocks != blocks.length) trailingBlocks = 0;
 
-    // Ignore any collections in the middle of the argument list.
-    if (leadingCollections == 0 && trailingCollections == 0) {
-      collections.clear();
+    // Ignore any blocks in the middle of the argument list.
+    if (leadingBlocks == 0 && trailingBlocks == 0) {
+      blocks.clear();
     }
 
-    return new ArgumentSublist._(allArguments, positional, named, collections,
-        leadingCollections, trailingCollections);
+    return new ArgumentSublist._(
+        allArguments, positional, named, blocks, leadingBlocks, trailingBlocks);
   }
 
   ArgumentSublist._(this._allArguments, this._positional, this._named,
-      this._collections, this._leadingCollections, this._trailingCollections);
+      this._blocks, this._leadingBlocks, this._trailingBlocks);
 
   void visit(SourceVisitor visitor) {
-    if (_collections.isNotEmpty) {
-      _collectionRule = new Rule(Cost.splitCollections);
+    if (_blocks.isNotEmpty) {
+      _blockRule = new Rule(Cost.splitBlocks);
     }
 
     var rule = _visitPositional(visitor);
@@ -390,11 +391,10 @@
     if (_positional.isEmpty) return null;
 
     // Allow splitting after "(".
-    // Only count the collections in the positional rule.
-    var leadingCollections = math.min(_leadingCollections, _positional.length);
-    var trailingCollections = math.max(_trailingCollections - _named.length, 0);
-    var rule = new PositionalRule(
-        _collectionRule, leadingCollections, trailingCollections);
+    // Only count the blocks in the positional rule.
+    var leadingBlocks = math.min(_leadingBlocks, _positional.length);
+    var trailingBlocks = math.max(_trailingBlocks - _named.length, 0);
+    var rule = new PositionalRule(_blockRule, leadingBlocks, trailingBlocks);
     _visitArguments(visitor, _positional, rule);
 
     return rule;
@@ -404,12 +404,10 @@
   void _visitNamed(SourceVisitor visitor, PositionalRule positionalRule) {
     if (_named.isEmpty) return;
 
-    // Only count the collections in the named rule.
-    var leadingCollections =
-        math.max(_leadingCollections - _positional.length, 0);
-    var trailingCollections = math.min(_trailingCollections, _named.length);
-    var namedRule =
-        new NamedRule(_collectionRule, leadingCollections, trailingCollections);
+    // Only count the blocks in the named rule.
+    var leadingBlocks = math.max(_leadingBlocks - _positional.length, 0);
+    var trailingBlocks = math.min(_trailingBlocks, _named.length);
+    var namedRule = new NamedRule(_blockRule, leadingBlocks, trailingBlocks);
 
     // Let the positional args force the named ones to split.
     if (positionalRule != null) {
@@ -450,12 +448,12 @@
 
   void _visitArgument(
       SourceVisitor visitor, ArgumentRule rule, Expression argument) {
-    // If we're about to write a collection argument, handle it specially.
-    if (_collections.containsKey(argument)) {
+    // If we're about to write a block argument, handle it specially.
+    if (_blocks.containsKey(argument)) {
       rule.disableSplitOnInnerRules();
 
       // Tell it to use the rule we've already created.
-      visitor.beforeCollection(_collections[argument], this);
+      visitor.beforeBlock(_blocks[argument], this);
     } else if (_allArguments.length > 1) {
       // Edge case: Only bump the nesting if there are multiple arguments. This
       // lets us avoid spurious indentation in cases like:
@@ -479,7 +477,7 @@
       visitor.visit(argument);
     }
 
-    if (_collections.containsKey(argument)) {
+    if (_blocks.containsKey(argument)) {
       rule.enableSplitOnInnerRules();
     } else if (_allArguments.length > 1) {
       visitor.builder.endBlockArgumentNesting();
@@ -493,12 +491,12 @@
     }
   }
 
-  /// Returns the token for the left bracket if [expression] denotes a
-  /// collection literal argument.
+  /// If [expression] can be formatted as a block, returns the token that opens
+  /// the block, such as a collection's bracket.
   ///
-  /// Similar to block functions, collection arguments can get special
-  /// indentation to make them look more statement-like.
-  static Token _getCollectionBracket(Expression expression) {
+  /// Block-formatted arguments can get special indentation to make them look
+  /// more statement-like.
+  static Token _blockToken(Expression expression) {
     if (expression is NamedExpression) {
       expression = (expression as NamedExpression).expression;
     }
@@ -507,6 +505,9 @@
 
     if (expression is ListLiteral) return expression.leftBracket;
     if (expression is MapLiteral) return expression.leftBracket;
+    if (expression is SingleStringLiteral && expression.isMultiline) {
+      return expression.beginToken;
+    }
 
     // Not a collection literal.
     return null;
diff --git a/pub/dart_style/lib/src/chunk.dart b/pub/dart_style/lib/src/chunk.dart
index 17a9218..3fd3e28 100644
--- a/pub/dart_style/lib/src/chunk.dart
+++ b/pub/dart_style/lib/src/chunk.dart
@@ -320,11 +320,11 @@
   /// Splitting inside the brackets of a list with only one element.
   static const singleElementList = 2;
 
-  /// Splitting the internals of collection literal arguments.
+  /// Splitting the internals of block arguments.
   ///
-  /// Used to prefer splitting at the argument boundary over splitting the
-  /// collection contents.
-  static const splitCollections = 2;
+  /// Used to prefer splitting at the argument boundary over splitting the block
+  /// contents.
+  static const splitBlocks = 2;
 
   /// Splitting on the "." in a named constructor.
   static const constructorName = 3;
diff --git a/pub/dart_style/lib/src/dart_formatter.dart b/pub/dart_style/lib/src/dart_formatter.dart
index 2e75e62..22d0a6a 100644
--- a/pub/dart_style/lib/src/dart_formatter.dart
+++ b/pub/dart_style/lib/src/dart_formatter.dart
@@ -103,7 +103,7 @@
 
     // Parse it.
     var parser = new Parser(stringSource, errorListener);
-    parser.parseGenericMethods = true;
+    parser.enableAssertInitializer = true;
 
     AstNode node;
     if (source.isCompilationUnit) {
diff --git a/pub/dart_style/lib/src/source_visitor.dart b/pub/dart_style/lib/src/source_visitor.dart
index 1104119..cef1340 100644
--- a/pub/dart_style/lib/src/source_visitor.dart
+++ b/pub/dart_style/lib/src/source_visitor.dart
@@ -68,20 +68,19 @@
   /// in unison.
   final List<MetadataRule> _metadataRules = [];
 
-  /// The mapping for collection literals that are managed by the argument
-  /// list that contains them.
+  /// The mapping for blocks that are managed by the argument list that contains
+  /// them.
   ///
-  /// When a collection literal appears inside an [ArgumentSublist], the
-  /// argument list provides a rule for the body to split to ensure that all
-  /// collections split in unison. It also tracks the chunk before the
-  /// argument that determines whether or not the collection body is indented
-  /// like an expression or a statement.
+  /// When a block expression, such as a collection literal or a multiline
+  /// string, appears inside an [ArgumentSublist], the argument list provides a
+  /// rule for the body to split to ensure that all blocks split in unison. It
+  /// also tracks the chunk before the argument that determines whether or not
+  /// the block body is indented like an expression or a statement.
   ///
-  /// Before a collection literal argument is visited, [ArgumentSublist] binds
-  /// itself to the left bracket token of each collection literal it controls.
-  /// When we later visit that literal, we use the token to find that
-  /// association.
-  final Map<Token, ArgumentSublist> _collectionArgumentLists = {};
+  /// Before a block argument is visited, [ArgumentSublist] binds itself to the
+  /// beginning token of each block it controls. When we later visit that
+  /// literal, we use the token to find that association.
+  final Map<Token, ArgumentSublist> _blockArgumentLists = {};
 
   /// Initialize a newly created visitor to write source code representing
   /// the visited nodes to the given [writer].
@@ -171,22 +170,17 @@
     builder.endSpan();
   }
 
-  // TODO(rnystrom): Type annotate once analyzer publishes a version with the
-  // new AST type.
-  // TODO(rnystrom): Test.
-  visitAssertInitializer(node) {
-    _simpleStatement(node, () {
-      token(node.assertKeyword);
+  visitAssertInitializer(AssertInitializer node) {
+    token(node.assertKeyword);
 
-      var arguments = <Expression>[node.condition];
-      if (node.message != null) arguments.add(node.message);
+    var arguments = <Expression>[node.condition];
+    if (node.message != null) arguments.add(node.message);
 
-      builder.nestExpression();
-      var visitor = new ArgumentListVisitor.forArguments(
-          this, node.leftParenthesis, node.rightParenthesis, arguments);
-      visitor.visit();
-      builder.unnest();
-    });
+    builder.nestExpression();
+    var visitor = new ArgumentListVisitor.forArguments(
+        this, node.leftParenthesis, node.rightParenthesis, arguments);
+    visitor.visit();
+    builder.unnest();
   }
 
   visitAssertStatement(AssertStatement node) {
@@ -2391,9 +2385,9 @@
     // handle splitting and indenting it. If not, we'll use a default rule.
     var rule;
     var argumentChunk;
-    if (_collectionArgumentLists.containsKey(leftBracket)) {
-      var argumentList = _collectionArgumentLists[leftBracket];
-      rule = argumentList.collectionRule;
+    if (_blockArgumentLists.containsKey(leftBracket)) {
+      var argumentList = _blockArgumentLists[leftBracket];
+      rule = argumentList.blockRule;
       argumentChunk = argumentList.previousSplit;
     }
 
@@ -2475,13 +2469,13 @@
     builder.unnest();
   }
 
-  /// Marks the collection literal that starts with [leftBracket] as being
-  /// controlled by [argumentList].
+  /// Marks the block that starts with [token] as being controlled by
+  /// [argumentList].
   ///
-  /// When the collection is visited, [argumentList] will determine the
-  /// indentation and splitting rule for the collection.
-  void beforeCollection(Token leftBracket, ArgumentSublist argumentList) {
-    _collectionArgumentLists[leftBracket] = argumentList;
+  /// When the block is visited, [argumentList] will determine the
+  /// indentation and splitting rule for the block.
+  void beforeBlock(Token token, ArgumentSublist argumentList) {
+    _blockArgumentLists[token] = argumentList;
   }
 
   /// Writes the beginning of a brace-delimited body and handles indenting and
@@ -2652,7 +2646,7 @@
         previousLine = commentLine;
       }
 
-      var text = comment.toString().trim();
+      var text = comment.lexeme.trim();
       var linesBefore = commentLine - previousLine;
       var flushLeft = _startColumn(comment) == 1;
 
diff --git a/pub/dart_style/pubspec.yaml b/pub/dart_style/pubspec.yaml
index 93ccf0c..7c26225 100644
--- a/pub/dart_style/pubspec.yaml
+++ b/pub/dart_style/pubspec.yaml
@@ -1,6 +1,6 @@
 name: dart_style
 # Note: See tool/grind.dart for how to bump the version.
-version: 1.0.6
+version: 1.0.7
 author: Dart Team <misc@dartlang.org>
 description: Opinionated, automatic Dart source code formatter.
 homepage: https://github.com/dart-lang/dart_style
diff --git a/pub/dart_style/test.dart b/pub/dart_style/test.dart
new file mode 100644
index 0000000..ed2a9a8
--- /dev/null
+++ b/pub/dart_style/test.dart
@@ -0,0 +1,4 @@
+var foo = "foo\n"
+  "bar"
+  "baz\n"
+  "bip" "binap";
\ No newline at end of file
diff --git a/pub/markdown/.travis.yml b/pub/markdown/.travis.yml
index abf77dd..8e02a6b 100644
--- a/pub/markdown/.travis.yml
+++ b/pub/markdown/.travis.yml
@@ -3,14 +3,18 @@
 dart:
   - stable
   - dev
+  - 1.23.0
   - 1.22.1
   - 1.21.1
-  - 1.20.1
-  - 1.19.1
 dart_task:
   - test: -p vm
   - dartfmt
   - dartanalyzer
+
+# Only building master means that we don't run two builds for each pull request.
+branches:
+  only: [master]
+
 cache:
   directories:
     - $HOME/.pub-cache
diff --git a/pub/markdown/BUILD.gn b/pub/markdown/BUILD.gn
index 3f80f77..92f72b2 100644
--- a/pub/markdown/BUILD.gn
+++ b/pub/markdown/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for markdown-0.11.3
+# This file is generated by importer.py for markdown-0.11.4
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/markdown/CHANGELOG.md b/pub/markdown/CHANGELOG.md
index 32fe122..469c685 100644
--- a/pub/markdown/CHANGELOG.md
+++ b/pub/markdown/CHANGELOG.md
@@ -1,6 +1,11 @@
+## 0.11.4
+
+* Fix bug with lazy blockquote continuations (#162)
+* Fix bug with list item continuations (#156)
+
 ## 0.11.3
 
-* Deprecated `escapeHtml`. This code exists in `dart:convert`.
+* Deprecate `escapeHtml`. This code exists in `dart:convert`.
 
 ## 0.11.2
 
@@ -9,12 +14,12 @@
 
 ## 0.11.1
 
-* Added version information:
+* Add version information:
   * `dart bin/markdown.dart --version` now shows the package version number.
   * The playground app now shows the version number.
 * Improve autolink parsing.
-* Added new table syntax: `TableSyntax`.
-* Added new ExtensionSet that includes the table syntax: `ExtensionSet.gitHub`.
+* Add new table syntax: `TableSyntax`.
+* Add new ExtensionSet that includes the table syntax: `ExtensionSet.gitHub`.
 * For development: added `tool/travis.sh`.
 * Support multiline Setext headers.
 * Handle loose-vs-strict list items better.
@@ -22,7 +27,7 @@
 
 ## 0.11.0+1
 
-* Added playground app at https://dart-lang.github.io/markdown.
+* Add playground app at https://dart-lang.github.io/markdown.
 
 ## 0.11.0
 
diff --git a/pub/markdown/README.md b/pub/markdown/README.md
index e128357..88c8028 100644
--- a/pub/markdown/README.md
+++ b/pub/markdown/README.md
@@ -91,6 +91,15 @@
   print(markdownToHtml('nyan', inlineSyntaxes: syntaxes));
   //=> <p>~=[,,_,,]:3</p>
 }
+
+### HTML Sanitization
+
+This package offers no features in the way of HTML sanitization. Read Estevão
+Soares dos Santos's great article, ["Markdown's XSS Vulnerability (and how to
+mitigate it)"], to learn more.
+
+The authors recommend that you perform any necessary sanitization on the
+resulting HTML, for example via `dart:html`'s [NodeValidator].
 ```
 
 ### CommonMark compliance
@@ -101,7 +110,7 @@
 #### Updating CommonMark stats when changing the implementation
 
  1. Update the library and test code, making sure that tests still pass.
- 2. Run `dart tool/common_mark_stats.dart --update-files` to update the
+ 2. Run `dart tool/stats.dart --update-files` to update the
     per-test results `tool/common_mark_stats.json` and the test summary
     `tool/common_mark_stats.txt`.
  3. Verify that more tests now pass – or at least, no more tests fail.
@@ -128,3 +137,5 @@
 [commonMark-raw-html]: http://spec.commonmark.org/0.27/#raw-html
 [CommonMark source]: https://github.com/jgm/CommonMark/
 [pandoc-auto_identifiers]: http://pandoc.org/README.html#extension-auto_identifiers
+["Markdown's XSS Vulnerability (and how to mitigate it)"]: https://github.com/showdownjs/showdown/wiki/Markdown%27s-XSS-Vulnerability-(and-how-to-mitigate-it)
+[NodeValidator]: https://api.dartlang.org/stable/latest/dart-html/NodeValidator-class.html
diff --git a/pub/markdown/.analysis_options b/pub/markdown/analysis_options.yaml
similarity index 70%
rename from pub/markdown/.analysis_options
rename to pub/markdown/analysis_options.yaml
index 37b2ae0..0eb0eaa 100644
--- a/pub/markdown/.analysis_options
+++ b/pub/markdown/analysis_options.yaml
@@ -1,37 +1,45 @@
 analyzer:
-  strong-mode: true
+ strong-mode: true
+ errors:
+   unused_element: error
+   unused_import: error
+   unused_local_variable: error
+   dead_code: error
 linter:
   rules:
-    - always_declare_return_types
+    #- always_declare_return_types
     #- always_specify_types
     #- annotate_overrides
     #- avoid_as
     - avoid_empty_else
     - avoid_init_to_null
-    - avoid_return_types_on_setters
+    - avoid_null_checks_in_equality_operators
+    #- avoid_return_types_on_setters
     - await_only_futures
     - camel_case_types
     - cancel_subscriptions
-    - close_sinks
-    #- comment_references
+    #- close_sinks
+    - comment_references
     - constant_identifier_names
     - control_flow_in_finally
+    - directives_ordering
     - empty_catches
     - empty_constructor_bodies
     - empty_statements
     - hash_and_equals
-    #- implementation_imports
+    - implementation_imports
     - iterable_contains_unrelated_type
     - library_names
     - library_prefixes
     - list_remove_unrelated_type
     #- non_constant_identifier_names
     #- one_member_abstracts
-    #- only_throw_errors
+    - only_throw_errors
     - overridden_fields
     - package_api_docs
     - package_names
     - package_prefixed_library_names
+    - prefer_final_fields
     - prefer_is_not_empty
     #- public_member_api_docs
     - slash_for_doc_comments
@@ -43,7 +51,7 @@
     #- type_annotate_public_apis
     - type_init_formals
     #- unawaited_futures
-    #- unnecessary_brace_in_string_interp
+    - unnecessary_brace_in_string_interp
     #- unnecessary_getters_setters
     - unrelated_type_equality_checks
     - valid_regexps
diff --git a/pub/markdown/lib/markdown.dart b/pub/markdown/lib/markdown.dart
index 9f4a11d..f4faacf 100644
--- a/pub/markdown/lib/markdown.dart
+++ b/pub/markdown/lib/markdown.dart
@@ -11,5 +11,5 @@
 export 'src/extension_set.dart';
 export 'src/html_renderer.dart';
 export 'src/inline_parser.dart';
-export 'src/version.dart';
 export 'src/util.dart' show escapeHtml;
+export 'src/version.dart';
diff --git a/pub/markdown/lib/src/block_parser.dart b/pub/markdown/lib/src/block_parser.dart
index f8555f8..80a98d0 100644
--- a/pub/markdown/lib/src/block_parser.dart
+++ b/pub/markdown/lib/src/block_parser.dart
@@ -335,10 +335,7 @@
       // a Setext header.
       if (parser.blockSyntaxes.firstWhere((s) => s.canParse(parser))
           is ParagraphSyntax) {
-        var continuedLine = childLines.last + parser.current;
-        childLines
-          ..removeLast()
-          ..add(continuedLine);
+        childLines.add(parser.current);
         parser.advance();
       } else {
         break;
@@ -531,18 +528,17 @@
   const OtherTagBlockHtmlSyntax();
 }
 
-/// A BlockHtmlSyntax that has a specific [endPattern].
+/// A BlockHtmlSyntax that has a specific `endPattern`.
 ///
 /// In practice this means that the syntax dominates; it is allowed to eat
-/// many lines, including blank lines, before matching its [endPattern].
+/// many lines, including blank lines, before matching its `endPattern`.
 class LongBlockHtmlSyntax extends BlockHtmlSyntax {
-  RegExp _pattern;
-  RegExp _endPattern;
+  final RegExp _pattern;
+  final RegExp _endPattern;
 
-  LongBlockHtmlSyntax(pattern, endPattern) {
-    _pattern = new RegExp(pattern);
-    _endPattern = new RegExp(endPattern);
-  }
+  LongBlockHtmlSyntax(pattern, endPattern)
+      : _pattern = new RegExp(pattern),
+        _endPattern = new RegExp(endPattern);
 
   RegExp get pattern => _pattern;
 
@@ -672,10 +668,7 @@
         }
 
         // Anything else is paragraph continuation text.
-        var continuedLine = childLines.last + parser.current;
-        childLines
-          ..removeLast()
-          ..add(continuedLine);
+        childLines.add(parser.current);
       }
       parser.advance();
     }
diff --git a/pub/markdown/lib/src/inline_parser.dart b/pub/markdown/lib/src/inline_parser.dart
index a1ebd92..2f4e243 100644
--- a/pub/markdown/lib/src/inline_parser.dart
+++ b/pub/markdown/lib/src/inline_parser.dart
@@ -431,7 +431,7 @@
   //
   // This conforms to the delimiters of inline code, both in Markdown.pl, and
   // CommonMark.
-  static String _pattern = r'(`+(?!`))((?:.|\n)*?[^`])\1(?!`)';
+  static final String _pattern = r'(`+(?!`))((?:.|\n)*?[^`])\1(?!`)';
 
   CodeSyntax() : super(_pattern);
 
diff --git a/pub/markdown/lib/src/version.dart b/pub/markdown/lib/src/version.dart
index 98092c4..c2a8126 100644
--- a/pub/markdown/lib/src/version.dart
+++ b/pub/markdown/lib/src/version.dart
@@ -1,2 +1,2 @@
 /// The current version of markdown.
-final String version = '0.11.3';
+final String version = '0.11.4';
diff --git a/pub/markdown/pubspec.yaml b/pub/markdown/pubspec.yaml
index fec5e69..308afda 100644
--- a/pub/markdown/pubspec.yaml
+++ b/pub/markdown/pubspec.yaml
@@ -1,5 +1,5 @@
 name: markdown
-version: 0.11.3
+version: 0.11.4
 author: Dart Team <misc@dartlang.org>
 description: A library for converting markdown to HTML.
 homepage: https://github.com/dart-lang/markdown
@@ -9,7 +9,8 @@
   args: '^0.13.3+1'
   # Only for example/app.dart.
   browser: any
-  collection: ^1.2.0
+  collection: '^1.2.0'
+  expected_output: '^1.1.0'
   html: '>=0.12.2 <0.14.0'
   js: '^0.6.1'
   path: '^1.3.1'
diff --git a/pub/markdown/tool/README.md b/pub/markdown/tool/README.md
index f2daa84..cd0e563 100644
--- a/pub/markdown/tool/README.md
+++ b/pub/markdown/tool/README.md
@@ -47,5 +47,5 @@
 runs the package through the CommonMark specs. To run it, simply run:
 
 ```bash
-$ dart tool/common_mark_stats.dart
+$ dart tool/stats.dart
 ```
diff --git a/pub/markdown/tool/gfm_stats.json b/pub/markdown/tool/gfm_stats.json
new file mode 100644
index 0000000..04e3836
--- /dev/null
+++ b/pub/markdown/tool/gfm_stats.json
@@ -0,0 +1,705 @@
+{
+ "ATX headings": {
+  "32": "fail",
+  "33": "strict",
+  "34": "strict",
+  "35": "strict",
+  "36": "fail",
+  "37": "fail",
+  "38": "fail",
+  "39": "strict",
+  "40": "loose",
+  "41": "fail",
+  "42": "fail",
+  "43": "fail",
+  "44": "fail",
+  "45": "fail",
+  "46": "fail",
+  "47": "fail",
+  "48": "fail",
+  "49": "fail"
+ },
+ "Autolinks": {
+  "574": "strict",
+  "575": "loose",
+  "576": "strict",
+  "577": "strict",
+  "578": "strict",
+  "579": "strict",
+  "580": "strict",
+  "581": "strict",
+  "582": "fail",
+  "583": "fail",
+  "584": "fail",
+  "585": "fail",
+  "586": "loose",
+  "587": "loose",
+  "588": "loose",
+  "589": "loose",
+  "590": "loose",
+  "591": "strict",
+  "592": "strict"
+ },
+ "Autolinks (extension)": {
+  "593": "fail",
+  "594": "fail",
+  "595": "fail",
+  "596": "fail",
+  "597": "fail",
+  "598": "fail",
+  "599": "fail",
+  "600": "fail",
+  "601": "fail",
+  "602": "fail",
+  "603": "fail"
+ },
+ "Backslash escapes": {
+  "296": "loose",
+  "297": "strict",
+  "298": "fail",
+  "299": "strict",
+  "300": "strict",
+  "301": "strict",
+  "302": "strict",
+  "303": "strict",
+  "304": "fail",
+  "305": "strict",
+  "306": "fail",
+  "307": "fail",
+  "308": "fail"
+ },
+ "Blank lines": {
+  "188": "fail"
+ },
+ "Block quotes": {
+  "196": "fail",
+  "197": "fail",
+  "198": "fail",
+  "199": "strict",
+  "200": "fail",
+  "201": "loose",
+  "202": "loose",
+  "203": "loose",
+  "204": "loose",
+  "205": "fail",
+  "206": "fail",
+  "207": "loose",
+  "208": "loose",
+  "209": "loose",
+  "210": "loose",
+  "211": "loose",
+  "212": "loose",
+  "213": "loose",
+  "214": "loose",
+  "215": "loose",
+  "216": "loose",
+  "217": "fail",
+  "218": "loose",
+  "219": "loose",
+  "220": "loose"
+ },
+ "Code spans": {
+  "321": "strict",
+  "322": "strict",
+  "323": "strict",
+  "324": "strict",
+  "325": "loose",
+  "326": "strict",
+  "327": "strict",
+  "328": "strict",
+  "329": "strict",
+  "330": "strict",
+  "331": "loose",
+  "332": "strict",
+  "333": "loose",
+  "334": "fail",
+  "335": "fail",
+  "336": "strict"
+ },
+ "Disallowed Raw HTML (extension)": {
+  "625": "fail"
+ },
+ "Emphasis and strong emphasis": {
+  "337": "strict",
+  "338": "strict",
+  "339": "fail",
+  "340": "fail",
+  "341": "strict",
+  "342": "strict",
+  "343": "strict",
+  "344": "fail",
+  "345": "loose",
+  "346": "strict",
+  "347": "strict",
+  "348": "fail",
+  "349": "loose",
+  "350": "strict",
+  "351": "strict",
+  "352": "fail",
+  "353": "fail",
+  "354": "fail",
+  "355": "fail",
+  "356": "strict",
+  "357": "fail",
+  "358": "strict",
+  "359": "strict",
+  "360": "strict",
+  "361": "fail",
+  "362": "strict",
+  "363": "strict",
+  "364": "strict",
+  "365": "fail",
+  "366": "fail",
+  "367": "strict",
+  "368": "strict",
+  "369": "fail",
+  "370": "fail",
+  "371": "loose",
+  "372": "strict",
+  "373": "strict",
+  "374": "fail",
+  "375": "strict",
+  "376": "strict",
+  "377": "fail",
+  "378": "fail",
+  "379": "fail",
+  "380": "strict",
+  "381": "loose",
+  "382": "strict",
+  "383": "fail",
+  "384": "strict",
+  "385": "strict",
+  "386": "strict",
+  "387": "fail",
+  "388": "strict",
+  "389": "strict",
+  "390": "strict",
+  "391": "strict",
+  "392": "strict",
+  "393": "strict",
+  "394": "fail",
+  "395": "fail",
+  "396": "fail",
+  "397": "fail",
+  "398": "fail",
+  "399": "fail",
+  "400": "fail",
+  "401": "fail",
+  "402": "fail",
+  "403": "strict",
+  "404": "fail",
+  "405": "strict",
+  "406": "strict",
+  "407": "strict",
+  "408": "strict",
+  "409": "fail",
+  "410": "fail",
+  "411": "strict",
+  "412": "strict",
+  "413": "strict",
+  "414": "strict",
+  "415": "fail",
+  "416": "strict",
+  "417": "strict",
+  "418": "fail",
+  "419": "strict",
+  "420": "strict",
+  "421": "strict",
+  "422": "fail",
+  "423": "strict",
+  "424": "strict",
+  "425": "fail",
+  "426": "strict",
+  "427": "fail",
+  "428": "fail",
+  "429": "strict",
+  "430": "strict",
+  "431": "strict",
+  "432": "strict",
+  "433": "strict",
+  "434": "fail",
+  "435": "strict",
+  "436": "strict",
+  "437": "fail",
+  "438": "loose",
+  "439": "loose",
+  "440": "fail",
+  "441": "loose",
+  "442": "loose",
+  "443": "strict",
+  "444": "strict",
+  "445": "strict",
+  "446": "strict",
+  "447": "fail",
+  "448": "fail",
+  "449": "fail",
+  "450": "fail",
+  "451": "fail",
+  "452": "strict",
+  "453": "fail",
+  "454": "loose",
+  "455": "loose",
+  "456": "fail",
+  "457": "fail",
+  "458": "strict",
+  "459": "strict",
+  "460": "strict",
+  "461": "strict",
+  "462": "strict",
+  "463": "strict",
+  "464": "strict"
+ },
+ "Entity and numeric character references": {
+  "309": "loose",
+  "310": "loose",
+  "311": "loose",
+  "312": "loose",
+  "313": "strict",
+  "314": "loose",
+  "315": "strict",
+  "316": "fail",
+  "317": "fail",
+  "318": "loose",
+  "319": "strict",
+  "320": "strict"
+ },
+ "Fenced code blocks": {
+  "88": "strict",
+  "89": "strict",
+  "90": "strict",
+  "91": "strict",
+  "92": "strict",
+  "93": "strict",
+  "94": "loose",
+  "95": "loose",
+  "96": "loose",
+  "97": "strict",
+  "98": "strict",
+  "99": "loose",
+  "100": "loose",
+  "101": "loose",
+  "102": "strict",
+  "103": "strict",
+  "104": "strict",
+  "105": "loose",
+  "106": "fail",
+  "107": "loose",
+  "108": "strict",
+  "109": "fail",
+  "110": "strict",
+  "111": "strict",
+  "112": "strict",
+  "113": "fail",
+  "114": "fail"
+ },
+ "Hard line breaks": {
+  "626": "strict",
+  "627": "strict",
+  "628": "strict",
+  "629": "loose",
+  "630": "loose",
+  "631": "strict",
+  "632": "strict",
+  "633": "loose",
+  "634": "loose",
+  "635": "strict",
+  "636": "strict",
+  "637": "strict",
+  "638": "loose",
+  "639": "fail",
+  "640": "fail"
+ },
+ "HTML blocks": {
+  "115": "strict",
+  "116": "strict",
+  "117": "strict",
+  "118": "loose",
+  "119": "strict",
+  "120": "strict",
+  "121": "strict",
+  "122": "strict",
+  "123": "strict",
+  "124": "strict",
+  "125": "strict",
+  "126": "strict",
+  "127": "strict",
+  "128": "strict",
+  "129": "strict",
+  "130": "strict",
+  "131": "strict",
+  "132": "strict",
+  "133": "loose",
+  "134": "strict",
+  "135": "strict",
+  "136": "strict",
+  "137": "strict",
+  "138": "loose",
+  "139": "loose",
+  "140": "loose",
+  "141": "strict",
+  "142": "strict",
+  "143": "strict",
+  "144": "strict",
+  "145": "strict",
+  "146": "strict",
+  "147": "strict",
+  "148": "strict",
+  "149": "strict",
+  "150": "loose",
+  "151": "strict",
+  "152": "strict",
+  "153": "loose",
+  "154": "strict",
+  "155": "loose",
+  "156": "loose"
+ },
+ "Images": {
+  "552": "loose",
+  "553": "loose",
+  "554": "fail",
+  "555": "loose",
+  "556": "loose",
+  "557": "loose",
+  "558": "loose",
+  "559": "loose",
+  "560": "loose",
+  "561": "loose",
+  "562": "loose",
+  "563": "loose",
+  "564": "loose",
+  "565": "loose",
+  "566": "loose",
+  "567": "loose",
+  "568": "loose",
+  "569": "loose",
+  "570": "loose",
+  "571": "loose",
+  "572": "strict",
+  "573": "strict"
+ },
+ "Indented code blocks": {
+  "76": "strict",
+  "77": "loose",
+  "78": "loose",
+  "79": "strict",
+  "80": "fail",
+  "81": "strict",
+  "82": "loose",
+  "83": "strict",
+  "84": "fail",
+  "85": "strict",
+  "86": "loose",
+  "87": "strict"
+ },
+ "Inlines": {
+  "295": "strict"
+ },
+ "Link reference definitions": {
+  "157": "strict",
+  "158": "strict",
+  "159": "fail",
+  "160": "strict",
+  "161": "strict",
+  "162": "strict",
+  "163": "strict",
+  "164": "strict",
+  "165": "fail",
+  "166": "strict",
+  "167": "strict",
+  "168": "strict",
+  "169": "fail",
+  "170": "loose",
+  "171": "strict",
+  "172": "loose",
+  "173": "loose",
+  "174": "loose",
+  "175": "strict",
+  "176": "strict",
+  "177": "fail",
+  "178": "strict",
+  "179": "loose"
+ },
+ "Links": {
+  "468": "strict",
+  "469": "strict",
+  "470": "strict",
+  "471": "strict",
+  "472": "strict",
+  "473": "loose",
+  "474": "strict",
+  "475": "fail",
+  "476": "fail",
+  "477": "fail",
+  "478": "fail",
+  "479": "fail",
+  "480": "fail",
+  "481": "strict",
+  "482": "fail",
+  "483": "fail",
+  "484": "fail",
+  "485": "fail",
+  "486": "fail",
+  "487": "fail",
+  "488": "loose",
+  "489": "fail",
+  "490": "fail",
+  "491": "strict",
+  "492": "fail",
+  "493": "strict",
+  "494": "strict",
+  "495": "strict",
+  "496": "fail",
+  "497": "loose",
+  "498": "fail",
+  "499": "fail",
+  "500": "fail",
+  "501": "fail",
+  "502": "strict",
+  "503": "strict",
+  "504": "strict",
+  "505": "strict",
+  "506": "fail",
+  "507": "strict",
+  "508": "loose",
+  "509": "strict",
+  "510": "fail",
+  "511": "loose",
+  "512": "loose",
+  "513": "fail",
+  "514": "fail",
+  "515": "strict",
+  "516": "strict",
+  "517": "strict",
+  "518": "fail",
+  "519": "strict",
+  "520": "strict",
+  "521": "fail",
+  "522": "strict",
+  "523": "strict",
+  "524": "strict",
+  "525": "strict",
+  "526": "fail",
+  "527": "strict",
+  "528": "strict",
+  "529": "strict",
+  "530": "strict",
+  "531": "strict",
+  "532": "loose",
+  "533": "strict",
+  "534": "strict",
+  "535": "strict",
+  "536": "loose",
+  "537": "strict",
+  "538": "strict",
+  "539": "strict",
+  "540": "strict",
+  "541": "strict",
+  "542": "strict",
+  "543": "strict",
+  "544": "fail",
+  "545": "strict",
+  "546": "strict",
+  "547": "strict",
+  "548": "strict",
+  "549": "loose",
+  "550": "strict",
+  "551": "loose"
+ },
+ "List items": {
+  "221": "loose",
+  "222": "loose",
+  "223": "loose",
+  "224": "loose",
+  "225": "loose",
+  "226": "loose",
+  "227": "loose",
+  "228": "loose",
+  "229": "strict",
+  "230": "fail",
+  "231": "loose",
+  "232": "fail",
+  "233": "loose",
+  "234": "strict",
+  "235": "loose",
+  "236": "loose",
+  "237": "strict",
+  "238": "loose",
+  "239": "loose",
+  "240": "strict",
+  "241": "loose",
+  "242": "loose",
+  "243": "loose",
+  "244": "loose",
+  "245": "loose",
+  "246": "loose",
+  "247": "loose",
+  "248": "fail",
+  "249": "loose",
+  "250": "loose",
+  "251": "loose",
+  "252": "loose",
+  "253": "fail",
+  "254": "loose",
+  "255": "loose",
+  "256": "loose",
+  "257": "strict",
+  "258": "loose",
+  "259": "loose",
+  "260": "loose",
+  "261": "loose",
+  "262": "loose",
+  "263": "loose",
+  "264": "loose",
+  "265": "loose",
+  "266": "loose",
+  "267": "loose",
+  "268": "fail"
+ },
+ "Lists": {
+  "271": "loose",
+  "272": "loose",
+  "273": "loose",
+  "274": "fail",
+  "275": "loose",
+  "276": "fail",
+  "277": "fail",
+  "278": "loose",
+  "279": "loose",
+  "280": "fail",
+  "281": "fail",
+  "282": "loose",
+  "283": "loose",
+  "284": "loose",
+  "285": "loose",
+  "286": "fail",
+  "287": "loose",
+  "288": "loose",
+  "289": "loose",
+  "290": "loose",
+  "291": "loose",
+  "292": "loose",
+  "293": "loose",
+  "294": "loose"
+ },
+ "Paragraphs": {
+  "180": "strict",
+  "181": "strict",
+  "182": "strict",
+  "183": "loose",
+  "184": "loose",
+  "185": "loose",
+  "186": "strict",
+  "187": "loose"
+ },
+ "Precedence": {
+  "12": "loose"
+ },
+ "Raw HTML": {
+  "604": "strict",
+  "605": "fail",
+  "606": "fail",
+  "607": "strict",
+  "608": "strict",
+  "609": "loose",
+  "610": "fail",
+  "611": "loose",
+  "612": "loose",
+  "613": "fail",
+  "614": "strict",
+  "615": "fail",
+  "616": "loose",
+  "617": "loose",
+  "618": "loose",
+  "619": "strict",
+  "620": "strict",
+  "621": "loose",
+  "622": "strict",
+  "623": "strict",
+  "624": "fail"
+ },
+ "Setext headings": {
+  "50": "fail",
+  "51": "fail",
+  "52": "fail",
+  "53": "fail",
+  "54": "strict",
+  "55": "fail",
+  "56": "loose",
+  "57": "strict",
+  "58": "fail",
+  "59": "fail",
+  "60": "fail",
+  "61": "loose",
+  "62": "fail",
+  "63": "loose",
+  "64": "fail",
+  "65": "fail",
+  "66": "strict",
+  "67": "strict",
+  "68": "loose",
+  "69": "strict",
+  "70": "loose",
+  "71": "fail",
+  "72": "fail",
+  "73": "strict",
+  "74": "strict",
+  "75": "strict"
+ },
+ "Soft line breaks": {
+  "641": "strict",
+  "642": "loose"
+ },
+ "Strikethrough (extension)": {
+  "465": "fail",
+  "466": "fail",
+  "467": "strict"
+ },
+ "Tables (extension)": {
+  "189": "loose",
+  "190": "fail",
+  "191": "loose",
+  "192": "fail",
+  "193": "fail",
+  "194": "fail",
+  "195": "fail"
+ },
+ "Tabs": {
+  "1": "strict",
+  "2": "fail",
+  "3": "strict",
+  "4": "fail",
+  "5": "fail",
+  "6": "loose",
+  "7": "loose",
+  "8": "strict",
+  "9": "fail",
+  "10": "fail",
+  "11": "fail"
+ },
+ "Textual content": {
+  "643": "strict",
+  "644": "strict",
+  "645": "strict"
+ },
+ "Thematic breaks": {
+  "13": "strict",
+  "14": "strict",
+  "15": "strict",
+  "16": "strict",
+  "17": "strict",
+  "18": "strict",
+  "19": "loose",
+  "20": "strict",
+  "21": "strict",
+  "22": "strict",
+  "23": "strict",
+  "24": "strict",
+  "25": "fail",
+  "26": "loose",
+  "27": "loose",
+  "28": "strict",
+  "29": "fail",
+  "30": "fail",
+  "31": "loose"
+ }
+}
diff --git a/pub/markdown/tool/gfm_stats.txt b/pub/markdown/tool/gfm_stats.txt
new file mode 100644
index 0000000..d741636
--- /dev/null
+++ b/pub/markdown/tool/gfm_stats.txt
@@ -0,0 +1,31 @@
+   5 of   18 –  27.8%  ATX headings
+  15 of   19 –  78.9%  Autolinks
+   0 of   11 –   0.0%  Autolinks (extension)
+   8 of   13 –  61.5%  Backslash escapes
+   0 of    1 –   0.0%  Blank lines
+  18 of   25 –  72.0%  Block quotes
+  14 of   16 –  87.5%  Code spans
+   0 of    1 –   0.0%  Disallowed Raw HTML (extension)
+  79 of  128 –  61.7%  Emphasis and strong emphasis
+  10 of   12 –  83.3%  Entity and numeric character references
+  23 of   27 –  85.2%  Fenced code blocks
+  13 of   15 –  86.7%  Hard line breaks
+  42 of   42 – 100.0%  HTML blocks
+  21 of   22 –  95.5%  Images
+  10 of   12 –  83.3%  Indented code blocks
+   1 of    1 – 100.0%  Inlines
+  19 of   23 –  82.6%  Link reference definitions
+  56 of   84 –  66.7%  Links
+  43 of   48 –  89.6%  List items
+  18 of   24 –  75.0%  Lists
+   8 of    8 – 100.0%  Paragraphs
+   1 of    1 – 100.0%  Precedence
+  15 of   21 –  71.4%  Raw HTML
+  13 of   26 –  50.0%  Setext headings
+   2 of    2 – 100.0%  Soft line breaks
+   1 of    3 –  33.3%  Strikethrough (extension)
+   2 of    7 –  28.6%  Tables (extension)
+   5 of   11 –  45.5%  Tabs
+   3 of    3 – 100.0%  Textual content
+  16 of   19 –  84.2%  Thematic breaks
+ 461 of  643 –  71.7%  TOTAL
diff --git a/pub/markdown/tool/gfm_tests.json b/pub/markdown/tool/gfm_tests.json
new file mode 100644
index 0000000..24c510f
--- /dev/null
+++ b/pub/markdown/tool/gfm_tests.json
@@ -0,0 +1,5833 @@
+[
+  {
+    "markdown": "\tfoo\tbaz\t\tbim\n",
+    "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n",
+    "example": 1,
+    "start_line": 360,
+    "end_line": 365,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "  \tfoo\tbaz\t\tbim\n",
+    "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n",
+    "example": 2,
+    "start_line": 367,
+    "end_line": 372,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "    a\ta\n    \u1f50\ta\n",
+    "html": "<pre><code>a\ta\n\u1f50\ta\n</code></pre>\n",
+    "example": 3,
+    "start_line": 374,
+    "end_line": 381,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "  - foo\n\n\tbar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 4,
+    "start_line": 387,
+    "end_line": 398,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n\t\tbar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code>  bar\n</code></pre>\n</li>\n</ul>\n",
+    "example": 5,
+    "start_line": 400,
+    "end_line": 412,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": ">\t\tfoo\n",
+    "html": "<blockquote>\n<pre><code>  foo\n</code></pre>\n</blockquote>\n",
+    "example": 6,
+    "start_line": 423,
+    "end_line": 430,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "-\t\tfoo\n",
+    "html": "<ul>\n<li>\n<pre><code>  foo\n</code></pre>\n</li>\n</ul>\n",
+    "example": 7,
+    "start_line": 432,
+    "end_line": 441,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo\n\tbar\n",
+    "html": "<pre><code>foo\nbar\n</code></pre>\n",
+    "example": 8,
+    "start_line": 444,
+    "end_line": 451,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": " - foo\n   - bar\n\t - baz\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 9,
+    "start_line": 453,
+    "end_line": 469,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "#\tFoo\n",
+    "html": "<h1>Foo</h1>\n",
+    "example": 10,
+    "start_line": 471,
+    "end_line": 475,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "*\t*\t*\t\n",
+    "html": "<hr />\n",
+    "example": 11,
+    "start_line": 477,
+    "end_line": 481,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "- `one\n- two`\n",
+    "html": "<ul>\n<li>`one</li>\n<li>two`</li>\n</ul>\n",
+    "example": 12,
+    "start_line": 504,
+    "end_line": 512,
+    "section": "Precedence",
+    "extensions": []
+  },
+  {
+    "markdown": "***\n---\n___\n",
+    "html": "<hr />\n<hr />\n<hr />\n",
+    "example": 13,
+    "start_line": 543,
+    "end_line": 551,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "+++\n",
+    "html": "<p>+++</p>\n",
+    "example": 14,
+    "start_line": 556,
+    "end_line": 560,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "===\n",
+    "html": "<p>===</p>\n",
+    "example": 15,
+    "start_line": 563,
+    "end_line": 567,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "--\n**\n__\n",
+    "html": "<p>--\n**\n__</p>\n",
+    "example": 16,
+    "start_line": 572,
+    "end_line": 580,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " ***\n  ***\n   ***\n",
+    "html": "<hr />\n<hr />\n<hr />\n",
+    "example": 17,
+    "start_line": 585,
+    "end_line": 593,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "    ***\n",
+    "html": "<pre><code>***\n</code></pre>\n",
+    "example": 18,
+    "start_line": 598,
+    "end_line": 603,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n    ***\n",
+    "html": "<p>Foo\n***</p>\n",
+    "example": 19,
+    "start_line": 606,
+    "end_line": 612,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "_____________________________________\n",
+    "html": "<hr />\n",
+    "example": 20,
+    "start_line": 617,
+    "end_line": 621,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " - - -\n",
+    "html": "<hr />\n",
+    "example": 21,
+    "start_line": 626,
+    "end_line": 630,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " **  * ** * ** * **\n",
+    "html": "<hr />\n",
+    "example": 22,
+    "start_line": 633,
+    "end_line": 637,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "-     -      -      -\n",
+    "html": "<hr />\n",
+    "example": 23,
+    "start_line": 640,
+    "end_line": 644,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "- - - -    \n",
+    "html": "<hr />\n",
+    "example": 24,
+    "start_line": 649,
+    "end_line": 653,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "_ _ _ _ a\n\na------\n\n---a---\n",
+    "html": "<p>_ _ _ _ a</p>\n<p>a------</p>\n<p>---a---</p>\n",
+    "example": 25,
+    "start_line": 658,
+    "end_line": 668,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " *-*\n",
+    "html": "<p><em>-</em></p>\n",
+    "example": 26,
+    "start_line": 674,
+    "end_line": 678,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n***\n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 27,
+    "start_line": 683,
+    "end_line": 695,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n***\nbar\n",
+    "html": "<p>Foo</p>\n<hr />\n<p>bar</p>\n",
+    "example": 28,
+    "start_line": 700,
+    "end_line": 708,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n---\nbar\n",
+    "html": "<h2>Foo</h2>\n<p>bar</p>\n",
+    "example": 29,
+    "start_line": 717,
+    "end_line": 724,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "* Foo\n* * *\n* Bar\n",
+    "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n<ul>\n<li>Bar</li>\n</ul>\n",
+    "example": 30,
+    "start_line": 730,
+    "end_line": 742,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "- Foo\n- * * *\n",
+    "html": "<ul>\n<li>Foo</li>\n<li>\n<hr />\n</li>\n</ul>\n",
+    "example": 31,
+    "start_line": 747,
+    "end_line": 757,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo\n## foo\n### foo\n#### foo\n##### foo\n###### foo\n",
+    "html": "<h1>foo</h1>\n<h2>foo</h2>\n<h3>foo</h3>\n<h4>foo</h4>\n<h5>foo</h5>\n<h6>foo</h6>\n",
+    "example": 32,
+    "start_line": 776,
+    "end_line": 790,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "####### foo\n",
+    "html": "<p>####### foo</p>\n",
+    "example": 33,
+    "start_line": 795,
+    "end_line": 799,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "#5 bolt\n\n#hashtag\n",
+    "html": "<p>#5 bolt</p>\n<p>#hashtag</p>\n",
+    "example": 34,
+    "start_line": 810,
+    "end_line": 817,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "\\## foo\n",
+    "html": "<p>## foo</p>\n",
+    "example": 35,
+    "start_line": 822,
+    "end_line": 826,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo *bar* \\*baz\\*\n",
+    "html": "<h1>foo <em>bar</em> *baz*</h1>\n",
+    "example": 36,
+    "start_line": 831,
+    "end_line": 835,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "#                  foo                     \n",
+    "html": "<h1>foo</h1>\n",
+    "example": 37,
+    "start_line": 840,
+    "end_line": 844,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": " ### foo\n  ## foo\n   # foo\n",
+    "html": "<h3>foo</h3>\n<h2>foo</h2>\n<h1>foo</h1>\n",
+    "example": 38,
+    "start_line": 849,
+    "end_line": 857,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    # foo\n",
+    "html": "<pre><code># foo\n</code></pre>\n",
+    "example": 39,
+    "start_line": 862,
+    "end_line": 867,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n    # bar\n",
+    "html": "<p>foo\n# bar</p>\n",
+    "example": 40,
+    "start_line": 870,
+    "end_line": 876,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "## foo ##\n  ###   bar    ###\n",
+    "html": "<h2>foo</h2>\n<h3>bar</h3>\n",
+    "example": 41,
+    "start_line": 881,
+    "end_line": 887,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo ##################################\n##### foo ##\n",
+    "html": "<h1>foo</h1>\n<h5>foo</h5>\n",
+    "example": 42,
+    "start_line": 892,
+    "end_line": 898,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo ###     \n",
+    "html": "<h3>foo</h3>\n",
+    "example": 43,
+    "start_line": 903,
+    "end_line": 907,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo ### b\n",
+    "html": "<h3>foo ### b</h3>\n",
+    "example": 44,
+    "start_line": 914,
+    "end_line": 918,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo#\n",
+    "html": "<h1>foo#</h1>\n",
+    "example": 45,
+    "start_line": 923,
+    "end_line": 927,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo \\###\n## foo #\\##\n# foo \\#\n",
+    "html": "<h3>foo ###</h3>\n<h2>foo ###</h2>\n<h1>foo #</h1>\n",
+    "example": 46,
+    "start_line": 933,
+    "end_line": 941,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "****\n## foo\n****\n",
+    "html": "<hr />\n<h2>foo</h2>\n<hr />\n",
+    "example": 47,
+    "start_line": 947,
+    "end_line": 955,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo bar\n# baz\nBar foo\n",
+    "html": "<p>Foo bar</p>\n<h1>baz</h1>\n<p>Bar foo</p>\n",
+    "example": 48,
+    "start_line": 958,
+    "end_line": 966,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "## \n#\n### ###\n",
+    "html": "<h2></h2>\n<h1></h1>\n<h3></h3>\n",
+    "example": 49,
+    "start_line": 971,
+    "end_line": 979,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo *bar*\n=========\n\nFoo *bar*\n---------\n",
+    "html": "<h1>Foo <em>bar</em></h1>\n<h2>Foo <em>bar</em></h2>\n",
+    "example": 50,
+    "start_line": 1014,
+    "end_line": 1023,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo *bar\nbaz*\n====\n",
+    "html": "<h1>Foo <em>bar\nbaz</em></h1>\n",
+    "example": 51,
+    "start_line": 1028,
+    "end_line": 1035,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n-------------------------\n\nFoo\n=\n",
+    "html": "<h2>Foo</h2>\n<h1>Foo</h1>\n",
+    "example": 52,
+    "start_line": 1040,
+    "end_line": 1049,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "   Foo\n---\n\n  Foo\n-----\n\n  Foo\n  ===\n",
+    "html": "<h2>Foo</h2>\n<h2>Foo</h2>\n<h1>Foo</h1>\n",
+    "example": 53,
+    "start_line": 1055,
+    "end_line": 1068,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    Foo\n    ---\n\n    Foo\n---\n",
+    "html": "<pre><code>Foo\n---\n\nFoo\n</code></pre>\n<hr />\n",
+    "example": 54,
+    "start_line": 1073,
+    "end_line": 1086,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n   ----      \n",
+    "html": "<h2>Foo</h2>\n",
+    "example": 55,
+    "start_line": 1092,
+    "end_line": 1097,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n    ---\n",
+    "html": "<p>Foo\n---</p>\n",
+    "example": 56,
+    "start_line": 1102,
+    "end_line": 1108,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n= =\n\nFoo\n--- -\n",
+    "html": "<p>Foo\n= =</p>\n<p>Foo</p>\n<hr />\n",
+    "example": 57,
+    "start_line": 1113,
+    "end_line": 1124,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo  \n-----\n",
+    "html": "<h2>Foo</h2>\n",
+    "example": 58,
+    "start_line": 1129,
+    "end_line": 1134,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\\\n----\n",
+    "html": "<h2>Foo\\</h2>\n",
+    "example": 59,
+    "start_line": 1139,
+    "end_line": 1144,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "`Foo\n----\n`\n\n<a title=\"a lot\n---\nof dashes\"/>\n",
+    "html": "<h2>`Foo</h2>\n<p>`</p>\n<h2>&lt;a title=&quot;a lot</h2>\n<p>of dashes&quot;/&gt;</p>\n",
+    "example": 60,
+    "start_line": 1150,
+    "end_line": 1163,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "> Foo\n---\n",
+    "html": "<blockquote>\n<p>Foo</p>\n</blockquote>\n<hr />\n",
+    "example": 61,
+    "start_line": 1169,
+    "end_line": 1177,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\nbar\n===\n",
+    "html": "<blockquote>\n<p>foo\nbar\n===</p>\n</blockquote>\n",
+    "example": 62,
+    "start_line": 1180,
+    "end_line": 1190,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "- Foo\n---\n",
+    "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n",
+    "example": 63,
+    "start_line": 1193,
+    "end_line": 1201,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nBar\n---\n",
+    "html": "<h2>Foo\nBar</h2>\n",
+    "example": 64,
+    "start_line": 1208,
+    "end_line": 1215,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "---\nFoo\n---\nBar\n---\nBaz\n",
+    "html": "<hr />\n<h2>Foo</h2>\n<h2>Bar</h2>\n<p>Baz</p>\n",
+    "example": 65,
+    "start_line": 1221,
+    "end_line": 1233,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "\n====\n",
+    "html": "<p>====</p>\n",
+    "example": 66,
+    "start_line": 1238,
+    "end_line": 1243,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "---\n---\n",
+    "html": "<hr />\n<hr />\n",
+    "example": 67,
+    "start_line": 1250,
+    "end_line": 1256,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n-----\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n",
+    "example": 68,
+    "start_line": 1259,
+    "end_line": 1267,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo\n---\n",
+    "html": "<pre><code>foo\n</code></pre>\n<hr />\n",
+    "example": 69,
+    "start_line": 1270,
+    "end_line": 1277,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n-----\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n",
+    "example": 70,
+    "start_line": 1280,
+    "end_line": 1288,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "\\> foo\n------\n",
+    "html": "<h2>&gt; foo</h2>\n",
+    "example": 71,
+    "start_line": 1294,
+    "end_line": 1299,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n\nbar\n---\nbaz\n",
+    "html": "<p>Foo</p>\n<h2>bar</h2>\n<p>baz</p>\n",
+    "example": 72,
+    "start_line": 1325,
+    "end_line": 1335,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nbar\n\n---\n\nbaz\n",
+    "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n",
+    "example": 73,
+    "start_line": 1341,
+    "end_line": 1353,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nbar\n* * *\nbaz\n",
+    "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n",
+    "example": 74,
+    "start_line": 1359,
+    "end_line": 1369,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nbar\n\\---\nbaz\n",
+    "html": "<p>Foo\nbar\n---\nbaz</p>\n",
+    "example": 75,
+    "start_line": 1374,
+    "end_line": 1384,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    a simple\n      indented code block\n",
+    "html": "<pre><code>a simple\n  indented code block\n</code></pre>\n",
+    "example": 76,
+    "start_line": 1402,
+    "end_line": 1409,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  - foo\n\n    bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 77,
+    "start_line": 1416,
+    "end_line": 1427,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "1.  foo\n\n    - bar\n",
+    "html": "<ol>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 78,
+    "start_line": 1430,
+    "end_line": 1443,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    <a/>\n    *hi*\n\n    - one\n",
+    "html": "<pre><code>&lt;a/&gt;\n*hi*\n\n- one\n</code></pre>\n",
+    "example": 79,
+    "start_line": 1450,
+    "end_line": 1461,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    chunk1\n\n    chunk2\n  \n \n \n    chunk3\n",
+    "html": "<pre><code>chunk1\n\nchunk2\n\n\n\nchunk3\n</code></pre>\n",
+    "example": 80,
+    "start_line": 1466,
+    "end_line": 1483,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    chunk1\n      \n      chunk2\n",
+    "html": "<pre><code>chunk1\n  \n  chunk2\n</code></pre>\n",
+    "example": 81,
+    "start_line": 1489,
+    "end_line": 1498,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n    bar\n\n",
+    "html": "<p>Foo\nbar</p>\n",
+    "example": 82,
+    "start_line": 1504,
+    "end_line": 1511,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo\nbar\n",
+    "html": "<pre><code>foo\n</code></pre>\n<p>bar</p>\n",
+    "example": 83,
+    "start_line": 1518,
+    "end_line": 1525,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "# Heading\n    foo\nHeading\n------\n    foo\n----\n",
+    "html": "<h1>Heading</h1>\n<pre><code>foo\n</code></pre>\n<h2>Heading</h2>\n<pre><code>foo\n</code></pre>\n<hr />\n",
+    "example": 84,
+    "start_line": 1531,
+    "end_line": 1546,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "        foo\n    bar\n",
+    "html": "<pre><code>    foo\nbar\n</code></pre>\n",
+    "example": 85,
+    "start_line": 1551,
+    "end_line": 1558,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "\n    \n    foo\n    \n\n",
+    "html": "<pre><code>foo\n</code></pre>\n",
+    "example": 86,
+    "start_line": 1564,
+    "end_line": 1573,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo  \n",
+    "html": "<pre><code>foo  \n</code></pre>\n",
+    "example": 87,
+    "start_line": 1578,
+    "end_line": 1583,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n<\n >\n```\n",
+    "html": "<pre><code>&lt;\n &gt;\n</code></pre>\n",
+    "example": 88,
+    "start_line": 1633,
+    "end_line": 1642,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~\n<\n >\n~~~\n",
+    "html": "<pre><code>&lt;\n &gt;\n</code></pre>\n",
+    "example": 89,
+    "start_line": 1647,
+    "end_line": 1656,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\naaa\n~~~\n```\n",
+    "html": "<pre><code>aaa\n~~~\n</code></pre>\n",
+    "example": 90,
+    "start_line": 1662,
+    "end_line": 1671,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~\naaa\n```\n~~~\n",
+    "html": "<pre><code>aaa\n```\n</code></pre>\n",
+    "example": 91,
+    "start_line": 1674,
+    "end_line": 1683,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "````\naaa\n```\n``````\n",
+    "html": "<pre><code>aaa\n```\n</code></pre>\n",
+    "example": 92,
+    "start_line": 1688,
+    "end_line": 1697,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~~\naaa\n~~~\n~~~~\n",
+    "html": "<pre><code>aaa\n~~~\n</code></pre>\n",
+    "example": 93,
+    "start_line": 1700,
+    "end_line": 1709,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n",
+    "html": "<pre><code></code></pre>\n",
+    "example": 94,
+    "start_line": 1715,
+    "end_line": 1719,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "`````\n\n```\naaa\n",
+    "html": "<pre><code>\n```\naaa\n</code></pre>\n",
+    "example": 95,
+    "start_line": 1722,
+    "end_line": 1732,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "> ```\n> aaa\n\nbbb\n",
+    "html": "<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>\n",
+    "example": 96,
+    "start_line": 1735,
+    "end_line": 1746,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n\n  \n```\n",
+    "html": "<pre><code>\n  \n</code></pre>\n",
+    "example": 97,
+    "start_line": 1751,
+    "end_line": 1760,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n```\n",
+    "html": "<pre><code></code></pre>\n",
+    "example": 98,
+    "start_line": 1765,
+    "end_line": 1770,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": " ```\n aaa\naaa\n```\n",
+    "html": "<pre><code>aaa\naaa\n</code></pre>\n",
+    "example": 99,
+    "start_line": 1777,
+    "end_line": 1786,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  ```\naaa\n  aaa\naaa\n  ```\n",
+    "html": "<pre><code>aaa\naaa\naaa\n</code></pre>\n",
+    "example": 100,
+    "start_line": 1789,
+    "end_line": 1800,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "   ```\n   aaa\n    aaa\n  aaa\n   ```\n",
+    "html": "<pre><code>aaa\n aaa\naaa\n</code></pre>\n",
+    "example": 101,
+    "start_line": 1803,
+    "end_line": 1814,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    ```\n    aaa\n    ```\n",
+    "html": "<pre><code>```\naaa\n```\n</code></pre>\n",
+    "example": 102,
+    "start_line": 1819,
+    "end_line": 1828,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\naaa\n  ```\n",
+    "html": "<pre><code>aaa\n</code></pre>\n",
+    "example": 103,
+    "start_line": 1834,
+    "end_line": 1841,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "   ```\naaa\n  ```\n",
+    "html": "<pre><code>aaa\n</code></pre>\n",
+    "example": 104,
+    "start_line": 1844,
+    "end_line": 1851,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\naaa\n    ```\n",
+    "html": "<pre><code>aaa\n    ```\n</code></pre>\n",
+    "example": 105,
+    "start_line": 1856,
+    "end_line": 1864,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "``` ```\naaa\n",
+    "html": "<p><code></code>\naaa</p>\n",
+    "example": 106,
+    "start_line": 1870,
+    "end_line": 1876,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~~~~\naaa\n~~~ ~~\n",
+    "html": "<pre><code>aaa\n~~~ ~~\n</code></pre>\n",
+    "example": 107,
+    "start_line": 1879,
+    "end_line": 1887,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n```\nbar\n```\nbaz\n",
+    "html": "<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n",
+    "example": 108,
+    "start_line": 1893,
+    "end_line": 1904,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n---\n~~~\nbar\n~~~\n# baz\n",
+    "html": "<h2>foo</h2>\n<pre><code>bar\n</code></pre>\n<h1>baz</h1>\n",
+    "example": 109,
+    "start_line": 1910,
+    "end_line": 1922,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```ruby\ndef foo(x)\n  return 3\nend\n```\n",
+    "html": "<pre><code class=\"language-ruby\">def foo(x)\n  return 3\nend\n</code></pre>\n",
+    "example": 110,
+    "start_line": 1930,
+    "end_line": 1941,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~~    ruby startline=3 $%@#$\ndef foo(x)\n  return 3\nend\n~~~~~~~\n",
+    "html": "<pre><code class=\"language-ruby\">def foo(x)\n  return 3\nend\n</code></pre>\n",
+    "example": 111,
+    "start_line": 1944,
+    "end_line": 1955,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "````;\n````\n",
+    "html": "<pre><code class=\"language-;\"></code></pre>\n",
+    "example": 112,
+    "start_line": 1958,
+    "end_line": 1963,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "``` aa ```\nfoo\n",
+    "html": "<p><code>aa</code>\nfoo</p>\n",
+    "example": 113,
+    "start_line": 1968,
+    "end_line": 1974,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n``` aaa\n```\n",
+    "html": "<pre><code>``` aaa\n</code></pre>\n",
+    "example": 114,
+    "start_line": 1979,
+    "end_line": 1986,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n\nokay.\n",
+    "html": "<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n<p>okay.</p>\n",
+    "example": 115,
+    "start_line": 2054,
+    "end_line": 2073,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": " <div>\n  *hello*\n         <foo><a>\n",
+    "html": " <div>\n  *hello*\n         <foo><a>\n",
+    "example": 116,
+    "start_line": 2076,
+    "end_line": 2084,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "</div>\n*foo*\n",
+    "html": "</div>\n*foo*\n",
+    "example": 117,
+    "start_line": 2089,
+    "end_line": 2095,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<DIV CLASS=\"foo\">\n\n*Markdown*\n\n</DIV>\n",
+    "html": "<DIV CLASS=\"foo\">\n<p><em>Markdown</em></p>\n</DIV>\n",
+    "example": 118,
+    "start_line": 2100,
+    "end_line": 2110,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div id=\"foo\"\n  class=\"bar\">\n</div>\n",
+    "html": "<div id=\"foo\"\n  class=\"bar\">\n</div>\n",
+    "example": 119,
+    "start_line": 2116,
+    "end_line": 2124,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div id=\"foo\" class=\"bar\n  baz\">\n</div>\n",
+    "html": "<div id=\"foo\" class=\"bar\n  baz\">\n</div>\n",
+    "example": 120,
+    "start_line": 2127,
+    "end_line": 2135,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\n*foo*\n\n*bar*\n",
+    "html": "<div>\n*foo*\n<p><em>bar</em></p>\n",
+    "example": 121,
+    "start_line": 2139,
+    "end_line": 2148,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div id=\"foo\"\n*hi*\n",
+    "html": "<div id=\"foo\"\n*hi*\n",
+    "example": 122,
+    "start_line": 2155,
+    "end_line": 2161,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div class\nfoo\n",
+    "html": "<div class\nfoo\n",
+    "example": 123,
+    "start_line": 2164,
+    "end_line": 2170,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div *???-&&&-<---\n*foo*\n",
+    "html": "<div *???-&&&-<---\n*foo*\n",
+    "example": 124,
+    "start_line": 2176,
+    "end_line": 2182,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div><a href=\"bar\">*foo*</a></div>\n",
+    "html": "<div><a href=\"bar\">*foo*</a></div>\n",
+    "example": 125,
+    "start_line": 2188,
+    "end_line": 2192,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table><tr><td>\nfoo\n</td></tr></table>\n",
+    "html": "<table><tr><td>\nfoo\n</td></tr></table>\n",
+    "example": 126,
+    "start_line": 2195,
+    "end_line": 2203,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div></div>\n``` c\nint x = 33;\n```\n",
+    "html": "<div></div>\n``` c\nint x = 33;\n```\n",
+    "example": 127,
+    "start_line": 2212,
+    "end_line": 2222,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"foo\">\n*bar*\n</a>\n",
+    "html": "<a href=\"foo\">\n*bar*\n</a>\n",
+    "example": 128,
+    "start_line": 2229,
+    "end_line": 2237,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<Warning>\n*bar*\n</Warning>\n",
+    "html": "<Warning>\n*bar*\n</Warning>\n",
+    "example": 129,
+    "start_line": 2242,
+    "end_line": 2250,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<i class=\"foo\">\n*bar*\n</i>\n",
+    "html": "<i class=\"foo\">\n*bar*\n</i>\n",
+    "example": 130,
+    "start_line": 2253,
+    "end_line": 2261,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "</ins>\n*bar*\n",
+    "html": "</ins>\n*bar*\n",
+    "example": 131,
+    "start_line": 2264,
+    "end_line": 2270,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<del>\n*foo*\n</del>\n",
+    "html": "<del>\n*foo*\n</del>\n",
+    "example": 132,
+    "start_line": 2279,
+    "end_line": 2287,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<del>\n\n*foo*\n\n</del>\n",
+    "html": "<del>\n<p><em>foo</em></p>\n</del>\n",
+    "example": 133,
+    "start_line": 2294,
+    "end_line": 2304,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<del>*foo*</del>\n",
+    "html": "<p><del><em>foo</em></del></p>\n",
+    "example": 134,
+    "start_line": 2312,
+    "end_line": 2316,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\nokay\n",
+    "html": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\n<p>okay</p>\n",
+    "example": 135,
+    "start_line": 2328,
+    "end_line": 2344,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\nokay\n",
+    "html": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\n<p>okay</p>\n",
+    "example": 136,
+    "start_line": 2349,
+    "end_line": 2363,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<style\n  type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\nokay\n",
+    "html": "<style\n  type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\n<p>okay</p>\n",
+    "example": 137,
+    "start_line": 2368,
+    "end_line": 2384,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<style\n  type=\"text/css\">\n\nfoo\n",
+    "html": "<style\n  type=\"text/css\">\n\nfoo\n",
+    "example": 138,
+    "start_line": 2391,
+    "end_line": 2401,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "> <div>\n> foo\n\nbar\n",
+    "html": "<blockquote>\n<div>\nfoo\n</blockquote>\n<p>bar</p>\n",
+    "example": 139,
+    "start_line": 2404,
+    "end_line": 2415,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "- <div>\n- foo\n",
+    "html": "<ul>\n<li>\n<div>\n</li>\n<li>foo</li>\n</ul>\n",
+    "example": 140,
+    "start_line": 2418,
+    "end_line": 2428,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<style>p{color:red;}</style>\n*foo*\n",
+    "html": "<style>p{color:red;}</style>\n<p><em>foo</em></p>\n",
+    "example": 141,
+    "start_line": 2433,
+    "end_line": 2439,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<!-- foo -->*bar*\n*baz*\n",
+    "html": "<!-- foo -->*bar*\n<p><em>baz</em></p>\n",
+    "example": 142,
+    "start_line": 2442,
+    "end_line": 2448,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<script>\nfoo\n</script>1. *bar*\n",
+    "html": "<script>\nfoo\n</script>1. *bar*\n",
+    "example": 143,
+    "start_line": 2454,
+    "end_line": 2462,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<!-- Foo\n\nbar\n   baz -->\nokay\n",
+    "html": "<!-- Foo\n\nbar\n   baz -->\n<p>okay</p>\n",
+    "example": 144,
+    "start_line": 2467,
+    "end_line": 2479,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<?php\n\n  echo '>';\n\n?>\nokay\n",
+    "html": "<?php\n\n  echo '>';\n\n?>\n<p>okay</p>\n",
+    "example": 145,
+    "start_line": 2485,
+    "end_line": 2499,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<!DOCTYPE html>\n",
+    "html": "<!DOCTYPE html>\n",
+    "example": 146,
+    "start_line": 2504,
+    "end_line": 2508,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\nokay\n",
+    "html": "<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\n<p>okay</p>\n",
+    "example": 147,
+    "start_line": 2513,
+    "end_line": 2541,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  <!-- foo -->\n\n    <!-- foo -->\n",
+    "html": "  <!-- foo -->\n<pre><code>&lt;!-- foo --&gt;\n</code></pre>\n",
+    "example": 148,
+    "start_line": 2546,
+    "end_line": 2554,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  <div>\n\n    <div>\n",
+    "html": "  <div>\n<pre><code>&lt;div&gt;\n</code></pre>\n",
+    "example": 149,
+    "start_line": 2557,
+    "end_line": 2565,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n<div>\nbar\n</div>\n",
+    "html": "<p>Foo</p>\n<div>\nbar\n</div>\n",
+    "example": 150,
+    "start_line": 2571,
+    "end_line": 2581,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\nbar\n</div>\n*foo*\n",
+    "html": "<div>\nbar\n</div>\n*foo*\n",
+    "example": 151,
+    "start_line": 2587,
+    "end_line": 2597,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n<a href=\"bar\">\nbaz\n",
+    "html": "<p>Foo\n<a href=\"bar\">\nbaz</p>\n",
+    "example": 152,
+    "start_line": 2602,
+    "end_line": 2610,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\n\n*Emphasized* text.\n\n</div>\n",
+    "html": "<div>\n<p><em>Emphasized</em> text.</p>\n</div>\n",
+    "example": 153,
+    "start_line": 2643,
+    "end_line": 2653,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\n*Emphasized* text.\n</div>\n",
+    "html": "<div>\n*Emphasized* text.\n</div>\n",
+    "example": 154,
+    "start_line": 2656,
+    "end_line": 2664,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table>\n\n<tr>\n\n<td>\nHi\n</td>\n\n</tr>\n\n</table>\n",
+    "html": "<table>\n<tr>\n<td>\nHi\n</td>\n</tr>\n</table>\n",
+    "example": 155,
+    "start_line": 2678,
+    "end_line": 2698,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table>\n\n  <tr>\n\n    <td>\n      Hi\n    </td>\n\n  </tr>\n\n</table>\n",
+    "html": "<table>\n  <tr>\n<pre><code>&lt;td&gt;\n  Hi\n&lt;/td&gt;\n</code></pre>\n  </tr>\n</table>\n",
+    "example": 156,
+    "start_line": 2705,
+    "end_line": 2726,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url \"title\"\n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 157,
+    "start_line": 2753,
+    "end_line": 2759,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "   [foo]: \n      /url  \n           'the title'  \n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"the title\">foo</a></p>\n",
+    "example": 158,
+    "start_line": 2762,
+    "end_line": 2770,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo*bar\\]]:my_(url) 'title (with parens)'\n\n[Foo*bar\\]]\n",
+    "html": "<p><a href=\"my_(url)\" title=\"title (with parens)\">Foo*bar]</a></p>\n",
+    "example": 159,
+    "start_line": 2773,
+    "end_line": 2779,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo bar]:\n<my%20url>\n'title'\n\n[Foo bar]\n",
+    "html": "<p><a href=\"my%20url\" title=\"title\">Foo bar</a></p>\n",
+    "example": 160,
+    "start_line": 2782,
+    "end_line": 2790,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url '\ntitle\nline1\nline2\n'\n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"\ntitle\nline1\nline2\n\">foo</a></p>\n",
+    "example": 161,
+    "start_line": 2795,
+    "end_line": 2809,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url 'title\n\nwith blank line'\n\n[foo]\n",
+    "html": "<p>[foo]: /url 'title</p>\n<p>with blank line'</p>\n<p>[foo]</p>\n",
+    "example": 162,
+    "start_line": 2814,
+    "end_line": 2824,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]:\n/url\n\n[foo]\n",
+    "html": "<p><a href=\"/url\">foo</a></p>\n",
+    "example": 163,
+    "start_line": 2829,
+    "end_line": 2836,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]:\n\n[foo]\n",
+    "html": "<p>[foo]:</p>\n<p>[foo]</p>\n",
+    "example": 164,
+    "start_line": 2841,
+    "end_line": 2848,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\\bar\\*baz \"foo\\\"bar\\baz\"\n\n[foo]\n",
+    "html": "<p><a href=\"/url%5Cbar*baz\" title=\"foo&quot;bar\\baz\">foo</a></p>\n",
+    "example": 165,
+    "start_line": 2854,
+    "end_line": 2860,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: url\n",
+    "html": "<p><a href=\"url\">foo</a></p>\n",
+    "example": 166,
+    "start_line": 2865,
+    "end_line": 2871,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: first\n[foo]: second\n",
+    "html": "<p><a href=\"first\">foo</a></p>\n",
+    "example": 167,
+    "start_line": 2877,
+    "end_line": 2884,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[FOO]: /url\n\n[Foo]\n",
+    "html": "<p><a href=\"/url\">Foo</a></p>\n",
+    "example": 168,
+    "start_line": 2890,
+    "end_line": 2896,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[\u0391\u0393\u03a9]: /\u03c6\u03bf\u03c5\n\n[\u03b1\u03b3\u03c9]\n",
+    "html": "<p><a href=\"/%CF%86%CE%BF%CF%85\">\u03b1\u03b3\u03c9</a></p>\n",
+    "example": 169,
+    "start_line": 2899,
+    "end_line": 2905,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\n",
+    "html": "",
+    "example": 170,
+    "start_line": 2911,
+    "end_line": 2914,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[\nfoo\n]: /url\nbar\n",
+    "html": "<p>bar</p>\n",
+    "example": 171,
+    "start_line": 2919,
+    "end_line": 2926,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url \"title\" ok\n",
+    "html": "<p>[foo]: /url &quot;title&quot; ok</p>\n",
+    "example": 172,
+    "start_line": 2932,
+    "end_line": 2936,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\n\"title\" ok\n",
+    "html": "<p>&quot;title&quot; ok</p>\n",
+    "example": 173,
+    "start_line": 2941,
+    "end_line": 2946,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "    [foo]: /url \"title\"\n\n[foo]\n",
+    "html": "<pre><code>[foo]: /url &quot;title&quot;\n</code></pre>\n<p>[foo]</p>\n",
+    "example": 174,
+    "start_line": 2952,
+    "end_line": 2960,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n[foo]: /url\n```\n\n[foo]\n",
+    "html": "<pre><code>[foo]: /url\n</code></pre>\n<p>[foo]</p>\n",
+    "example": 175,
+    "start_line": 2966,
+    "end_line": 2976,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n[bar]: /baz\n\n[bar]\n",
+    "html": "<p>Foo\n[bar]: /baz</p>\n<p>[bar]</p>\n",
+    "example": 176,
+    "start_line": 2981,
+    "end_line": 2990,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "# [Foo]\n[foo]: /url\n> bar\n",
+    "html": "<h1><a href=\"/url\">Foo</a></h1>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 177,
+    "start_line": 2996,
+    "end_line": 3005,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /foo-url \"foo\"\n[bar]: /bar-url\n  \"bar\"\n[baz]: /baz-url\n\n[foo],\n[bar],\n[baz]\n",
+    "html": "<p><a href=\"/foo-url\" title=\"foo\">foo</a>,\n<a href=\"/bar-url\" title=\"bar\">bar</a>,\n<a href=\"/baz-url\">baz</a></p>\n",
+    "example": 178,
+    "start_line": 3011,
+    "end_line": 3024,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n> [foo]: /url\n",
+    "html": "<p><a href=\"/url\">foo</a></p>\n<blockquote>\n</blockquote>\n",
+    "example": 179,
+    "start_line": 3032,
+    "end_line": 3040,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\n\nbbb\n",
+    "html": "<p>aaa</p>\n<p>bbb</p>\n",
+    "example": 180,
+    "start_line": 3055,
+    "end_line": 3062,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\nbbb\n\nccc\nddd\n",
+    "html": "<p>aaa\nbbb</p>\n<p>ccc\nddd</p>\n",
+    "example": 181,
+    "start_line": 3067,
+    "end_line": 3078,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\n\n\nbbb\n",
+    "html": "<p>aaa</p>\n<p>bbb</p>\n",
+    "example": 182,
+    "start_line": 3083,
+    "end_line": 3091,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "  aaa\n bbb\n",
+    "html": "<p>aaa\nbbb</p>\n",
+    "example": 183,
+    "start_line": 3096,
+    "end_line": 3102,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\n             bbb\n                                       ccc\n",
+    "html": "<p>aaa\nbbb\nccc</p>\n",
+    "example": 184,
+    "start_line": 3108,
+    "end_line": 3116,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "   aaa\nbbb\n",
+    "html": "<p>aaa\nbbb</p>\n",
+    "example": 185,
+    "start_line": 3122,
+    "end_line": 3128,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "    aaa\nbbb\n",
+    "html": "<pre><code>aaa\n</code></pre>\n<p>bbb</p>\n",
+    "example": 186,
+    "start_line": 3131,
+    "end_line": 3138,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa     \nbbb     \n",
+    "html": "<p>aaa<br />\nbbb</p>\n",
+    "example": 187,
+    "start_line": 3145,
+    "end_line": 3151,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "  \n\naaa\n  \n\n# aaa\n\n  \n",
+    "html": "<p>aaa</p>\n<h1>aaa</h1>\n",
+    "example": 188,
+    "start_line": 3162,
+    "end_line": 3174,
+    "section": "Blank lines",
+    "extensions": []
+  },
+  {
+    "markdown": "| foo | bar |\n| --- | --- |\n| baz | bim |\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>foo</th>\n<th>bar</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>baz</td>\n<td>bim</td>\n</tr></tbody></table>\n",
+    "example": 189,
+    "start_line": 3197,
+    "end_line": 3214,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | defghi |\n:-: | -----------:\nbar | baz\n",
+    "html": "<table>\n<thead>\n<tr>\n<th align=\"center\">abc</th>\n<th align=\"right\">defghi</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\">bar</td>\n<td align=\"right\">baz</td>\n</tr></tbody></table>\n",
+    "example": 190,
+    "start_line": 3219,
+    "end_line": 3236,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| f\\|oo  |\n| ------ |\n| b `\\|` az |\n| b **\\|** im |\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>f|oo</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b <code>|</code> az</td>\n</tr>\n<tr>\n<td>b <strong>|</strong> im</td>\n</tr></tbody></table>\n",
+    "example": 191,
+    "start_line": 3241,
+    "end_line": 3260,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- | --- |\n| bar | baz |\n> bar\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr></tbody></table>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 192,
+    "start_line": 3265,
+    "end_line": 3286,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- | --- |\n| bar | baz |\nbar\n\nbar\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr>\n<tr>\n<td>bar</td>\n<td></td>\n</tr></tbody></table>\n<p>bar</p>\n",
+    "example": 193,
+    "start_line": 3288,
+    "end_line": 3313,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- |\n| bar |\n",
+    "html": "<p>| abc | def |\n| --- |\n| bar |</p>\n",
+    "example": 194,
+    "start_line": 3318,
+    "end_line": 3326,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- | --- |\n| bar |\n| bar | baz | boo |\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td></td>\n</tr>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr></tbody></table>\n",
+    "example": 195,
+    "start_line": 3332,
+    "end_line": 3354,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "> # Foo\n> bar\n> baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 196,
+    "start_line": 3408,
+    "end_line": 3418,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "># Foo\n>bar\n> baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 197,
+    "start_line": 3423,
+    "end_line": 3433,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "   > # Foo\n   > bar\n > baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 198,
+    "start_line": 3438,
+    "end_line": 3448,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "    > # Foo\n    > bar\n    > baz\n",
+    "html": "<pre><code>&gt; # Foo\n&gt; bar\n&gt; baz\n</code></pre>\n",
+    "example": 199,
+    "start_line": 3453,
+    "end_line": 3462,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> # Foo\n> bar\nbaz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 200,
+    "start_line": 3468,
+    "end_line": 3478,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\nbaz\n> foo\n",
+    "html": "<blockquote>\n<p>bar\nbaz\nfoo</p>\n</blockquote>\n",
+    "example": 201,
+    "start_line": 3484,
+    "end_line": 3494,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n---\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n",
+    "example": 202,
+    "start_line": 3508,
+    "end_line": 3516,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> - foo\n- bar\n",
+    "html": "<blockquote>\n<ul>\n<li>foo</li>\n</ul>\n</blockquote>\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 203,
+    "start_line": 3528,
+    "end_line": 3540,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">     foo\n    bar\n",
+    "html": "<blockquote>\n<pre><code>foo\n</code></pre>\n</blockquote>\n<pre><code>bar\n</code></pre>\n",
+    "example": 204,
+    "start_line": 3546,
+    "end_line": 3556,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> ```\nfoo\n```\n",
+    "html": "<blockquote>\n<pre><code></code></pre>\n</blockquote>\n<p>foo</p>\n<pre><code></code></pre>\n",
+    "example": 205,
+    "start_line": 3559,
+    "end_line": 3569,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n    - bar\n",
+    "html": "<blockquote>\n<p>foo\n- bar</p>\n</blockquote>\n",
+    "example": 206,
+    "start_line": 3575,
+    "end_line": 3583,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">\n",
+    "html": "<blockquote>\n</blockquote>\n",
+    "example": 207,
+    "start_line": 3599,
+    "end_line": 3604,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">\n>  \n> \n",
+    "html": "<blockquote>\n</blockquote>\n",
+    "example": 208,
+    "start_line": 3607,
+    "end_line": 3614,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">\n> foo\n>  \n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n",
+    "example": 209,
+    "start_line": 3619,
+    "end_line": 3627,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n\n> bar\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 210,
+    "start_line": 3632,
+    "end_line": 3643,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n> bar\n",
+    "html": "<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n",
+    "example": 211,
+    "start_line": 3654,
+    "end_line": 3662,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n>\n> bar\n",
+    "html": "<blockquote>\n<p>foo</p>\n<p>bar</p>\n</blockquote>\n",
+    "example": 212,
+    "start_line": 3667,
+    "end_line": 3676,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n> bar\n",
+    "html": "<p>foo</p>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 213,
+    "start_line": 3681,
+    "end_line": 3689,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> aaa\n***\n> bbb\n",
+    "html": "<blockquote>\n<p>aaa</p>\n</blockquote>\n<hr />\n<blockquote>\n<p>bbb</p>\n</blockquote>\n",
+    "example": 214,
+    "start_line": 3695,
+    "end_line": 3707,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\nbaz\n",
+    "html": "<blockquote>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 215,
+    "start_line": 3713,
+    "end_line": 3721,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\n\nbaz\n",
+    "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n",
+    "example": 216,
+    "start_line": 3724,
+    "end_line": 3733,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\n>\nbaz\n",
+    "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n",
+    "example": 217,
+    "start_line": 3736,
+    "end_line": 3745,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> > > foo\nbar\n",
+    "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n</blockquote>\n</blockquote>\n",
+    "example": 218,
+    "start_line": 3752,
+    "end_line": 3764,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">>> foo\n> bar\n>>baz\n",
+    "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar\nbaz</p>\n</blockquote>\n</blockquote>\n</blockquote>\n",
+    "example": 219,
+    "start_line": 3767,
+    "end_line": 3781,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">     code\n\n>    not code\n",
+    "html": "<blockquote>\n<pre><code>code\n</code></pre>\n</blockquote>\n<blockquote>\n<p>not code</p>\n</blockquote>\n",
+    "example": 220,
+    "start_line": 3789,
+    "end_line": 3801,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "A paragraph\nwith two lines.\n\n    indented code\n\n> A block quote.\n",
+    "html": "<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n",
+    "example": 221,
+    "start_line": 3840,
+    "end_line": 3855,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.  A paragraph\n    with two lines.\n\n        indented code\n\n    > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 222,
+    "start_line": 3862,
+    "end_line": 3881,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- one\n\n two\n",
+    "html": "<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n",
+    "example": 223,
+    "start_line": 3895,
+    "end_line": 3904,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- one\n\n  two\n",
+    "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n",
+    "example": 224,
+    "start_line": 3907,
+    "end_line": 3918,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": " -    one\n\n     two\n",
+    "html": "<ul>\n<li>one</li>\n</ul>\n<pre><code> two\n</code></pre>\n",
+    "example": 225,
+    "start_line": 3921,
+    "end_line": 3931,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": " -    one\n\n      two\n",
+    "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n",
+    "example": 226,
+    "start_line": 3934,
+    "end_line": 3945,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "   > > 1.  one\n>>\n>>     two\n",
+    "html": "<blockquote>\n<blockquote>\n<ol>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ol>\n</blockquote>\n</blockquote>\n",
+    "example": 227,
+    "start_line": 3956,
+    "end_line": 3971,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": ">>- one\n>>\n  >  > two\n",
+    "html": "<blockquote>\n<blockquote>\n<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n</blockquote>\n</blockquote>\n",
+    "example": 228,
+    "start_line": 3983,
+    "end_line": 3996,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-one\n\n2.two\n",
+    "html": "<p>-one</p>\n<p>2.two</p>\n",
+    "example": 229,
+    "start_line": 4002,
+    "end_line": 4009,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n\n  bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 230,
+    "start_line": 4015,
+    "end_line": 4027,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.  foo\n\n    ```\n    bar\n    ```\n\n    baz\n\n    > bam\n",
+    "html": "<ol>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n<blockquote>\n<p>bam</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 231,
+    "start_line": 4032,
+    "end_line": 4054,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- Foo\n\n      bar\n\n\n      baz\n",
+    "html": "<ul>\n<li>\n<p>Foo</p>\n<pre><code>bar\n\n\nbaz\n</code></pre>\n</li>\n</ul>\n",
+    "example": 232,
+    "start_line": 4060,
+    "end_line": 4078,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "123456789. ok\n",
+    "html": "<ol start=\"123456789\">\n<li>ok</li>\n</ol>\n",
+    "example": 233,
+    "start_line": 4082,
+    "end_line": 4088,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1234567890. not ok\n",
+    "html": "<p>1234567890. not ok</p>\n",
+    "example": 234,
+    "start_line": 4091,
+    "end_line": 4095,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "0. ok\n",
+    "html": "<ol start=\"0\">\n<li>ok</li>\n</ol>\n",
+    "example": 235,
+    "start_line": 4100,
+    "end_line": 4106,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "003. ok\n",
+    "html": "<ol start=\"3\">\n<li>ok</li>\n</ol>\n",
+    "example": 236,
+    "start_line": 4109,
+    "end_line": 4115,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-1. not ok\n",
+    "html": "<p>-1. not ok</p>\n",
+    "example": 237,
+    "start_line": 4120,
+    "end_line": 4124,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n      bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ul>\n",
+    "example": 238,
+    "start_line": 4144,
+    "end_line": 4156,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  10.  foo\n\n           bar\n",
+    "html": "<ol start=\"10\">\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ol>\n",
+    "example": 239,
+    "start_line": 4161,
+    "end_line": 4173,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "    indented code\n\nparagraph\n\n    more code\n",
+    "html": "<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n",
+    "example": 240,
+    "start_line": 4180,
+    "end_line": 4192,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.     indented code\n\n   paragraph\n\n       more code\n",
+    "html": "<ol>\n<li>\n<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n",
+    "example": 241,
+    "start_line": 4195,
+    "end_line": 4211,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.      indented code\n\n   paragraph\n\n       more code\n",
+    "html": "<ol>\n<li>\n<pre><code> indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n",
+    "example": 242,
+    "start_line": 4217,
+    "end_line": 4233,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "   foo\n\nbar\n",
+    "html": "<p>foo</p>\n<p>bar</p>\n",
+    "example": 243,
+    "start_line": 4244,
+    "end_line": 4251,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-    foo\n\n  bar\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<p>bar</p>\n",
+    "example": 244,
+    "start_line": 4254,
+    "end_line": 4263,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-  foo\n\n   bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 245,
+    "start_line": 4271,
+    "end_line": 4282,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-\n  foo\n-\n  ```\n  bar\n  ```\n-\n      baz\n",
+    "html": "<ul>\n<li>foo</li>\n<li>\n<pre><code>bar\n</code></pre>\n</li>\n<li>\n<pre><code>baz\n</code></pre>\n</li>\n</ul>\n",
+    "example": 246,
+    "start_line": 4299,
+    "end_line": 4320,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-   \n  foo\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n",
+    "example": 247,
+    "start_line": 4325,
+    "end_line": 4332,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-\n\n  foo\n",
+    "html": "<ul>\n<li></li>\n</ul>\n<p>foo</p>\n",
+    "example": 248,
+    "start_line": 4339,
+    "end_line": 4348,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n-\n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n",
+    "example": 249,
+    "start_line": 4353,
+    "end_line": 4363,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n-   \n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n",
+    "example": 250,
+    "start_line": 4368,
+    "end_line": 4378,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1. foo\n2.\n3. bar\n",
+    "html": "<ol>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ol>\n",
+    "example": 251,
+    "start_line": 4383,
+    "end_line": 4393,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "*\n",
+    "html": "<ul>\n<li></li>\n</ul>\n",
+    "example": 252,
+    "start_line": 4398,
+    "end_line": 4404,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n*\n\nfoo\n1.\n",
+    "html": "<p>foo\n*</p>\n<p>foo\n1.</p>\n",
+    "example": 253,
+    "start_line": 4408,
+    "end_line": 4419,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": " 1.  A paragraph\n     with two lines.\n\n         indented code\n\n     > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 254,
+    "start_line": 4430,
+    "end_line": 4449,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  1.  A paragraph\n      with two lines.\n\n          indented code\n\n      > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 255,
+    "start_line": 4454,
+    "end_line": 4473,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "   1.  A paragraph\n       with two lines.\n\n           indented code\n\n       > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 256,
+    "start_line": 4478,
+    "end_line": 4497,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "    1.  A paragraph\n        with two lines.\n\n            indented code\n\n        > A block quote.\n",
+    "html": "<pre><code>1.  A paragraph\n    with two lines.\n\n        indented code\n\n    &gt; A block quote.\n</code></pre>\n",
+    "example": 257,
+    "start_line": 4502,
+    "end_line": 4517,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  1.  A paragraph\nwith two lines.\n\n          indented code\n\n      > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 258,
+    "start_line": 4532,
+    "end_line": 4551,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  1.  A paragraph\n    with two lines.\n",
+    "html": "<ol>\n<li>A paragraph\nwith two lines.</li>\n</ol>\n",
+    "example": 259,
+    "start_line": 4556,
+    "end_line": 4564,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "> 1. > Blockquote\ncontinued here.\n",
+    "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n",
+    "example": 260,
+    "start_line": 4569,
+    "end_line": 4583,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "> 1. > Blockquote\n> continued here.\n",
+    "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n",
+    "example": 261,
+    "start_line": 4586,
+    "end_line": 4600,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n  - bar\n    - baz\n      - boo\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz\n<ul>\n<li>boo</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 262,
+    "start_line": 4613,
+    "end_line": 4634,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n - bar\n  - baz\n   - boo\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n<li>baz</li>\n<li>boo</li>\n</ul>\n",
+    "example": 263,
+    "start_line": 4639,
+    "end_line": 4651,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "10) foo\n    - bar\n",
+    "html": "<ol start=\"10\">\n<li>foo\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 264,
+    "start_line": 4656,
+    "end_line": 4667,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "10) foo\n   - bar\n",
+    "html": "<ol start=\"10\">\n<li>foo</li>\n</ol>\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 265,
+    "start_line": 4672,
+    "end_line": 4682,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- - foo\n",
+    "html": "<ul>\n<li>\n<ul>\n<li>foo</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 266,
+    "start_line": 4687,
+    "end_line": 4697,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1. - 2. foo\n",
+    "html": "<ol>\n<li>\n<ul>\n<li>\n<ol start=\"2\">\n<li>foo</li>\n</ol>\n</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 267,
+    "start_line": 4700,
+    "end_line": 4714,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- # Foo\n- Bar\n  ---\n  baz\n",
+    "html": "<ul>\n<li>\n<h1>Foo</h1>\n</li>\n<li>\n<h2>Bar</h2>\nbaz</li>\n</ul>\n",
+    "example": 268,
+    "start_line": 4719,
+    "end_line": 4733,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n- bar\n+ baz\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<ul>\n<li>baz</li>\n</ul>\n",
+    "example": 271,
+    "start_line": 5012,
+    "end_line": 5024,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "1. foo\n2. bar\n3) baz\n",
+    "html": "<ol>\n<li>foo</li>\n<li>bar</li>\n</ol>\n<ol start=\"3\">\n<li>baz</li>\n</ol>\n",
+    "example": 272,
+    "start_line": 5027,
+    "end_line": 5039,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n- bar\n- baz\n",
+    "html": "<p>Foo</p>\n<ul>\n<li>bar</li>\n<li>baz</li>\n</ul>\n",
+    "example": 273,
+    "start_line": 5046,
+    "end_line": 5056,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "The number of windows in my house is\n14.  The number of doors is 6.\n",
+    "html": "<p>The number of windows in my house is\n14.  The number of doors is 6.</p>\n",
+    "example": 274,
+    "start_line": 5123,
+    "end_line": 5129,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "The number of windows in my house is\n1.  The number of doors is 6.\n",
+    "html": "<p>The number of windows in my house is</p>\n<ol>\n<li>The number of doors is 6.</li>\n</ol>\n",
+    "example": 275,
+    "start_line": 5133,
+    "end_line": 5141,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n- bar\n\n\n- baz\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n</li>\n<li>\n<p>bar</p>\n</li>\n<li>\n<p>baz</p>\n</li>\n</ul>\n",
+    "example": 276,
+    "start_line": 5147,
+    "end_line": 5166,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n  - bar\n    - baz\n\n\n      bim\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>\n<p>baz</p>\n<p>bim</p>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 277,
+    "start_line": 5168,
+    "end_line": 5190,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n- bar\n\n<!-- -->\n\n- baz\n- bim\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<!-- -->\n<ul>\n<li>baz</li>\n<li>bim</li>\n</ul>\n",
+    "example": 278,
+    "start_line": 5198,
+    "end_line": 5216,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "-   foo\n\n    notcode\n\n-   foo\n\n<!-- -->\n\n    code\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>notcode</p>\n</li>\n<li>\n<p>foo</p>\n</li>\n</ul>\n<!-- -->\n<pre><code>code\n</code></pre>\n",
+    "example": 279,
+    "start_line": 5219,
+    "end_line": 5242,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n - b\n  - c\n   - d\n    - e\n   - f\n  - g\n - h\n- i\n",
+    "html": "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d</li>\n<li>e</li>\n<li>f</li>\n<li>g</li>\n<li>h</li>\n<li>i</li>\n</ul>\n",
+    "example": 280,
+    "start_line": 5250,
+    "end_line": 5272,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "1. a\n\n  2. b\n\n    3. c\n",
+    "html": "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ol>\n",
+    "example": 281,
+    "start_line": 5275,
+    "end_line": 5293,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- b\n\n- c\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ul>\n",
+    "example": 282,
+    "start_line": 5299,
+    "end_line": 5316,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "* a\n*\n\n* c\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>c</p>\n</li>\n</ul>\n",
+    "example": 283,
+    "start_line": 5321,
+    "end_line": 5336,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- b\n\n  c\n- d\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n",
+    "example": 284,
+    "start_line": 5343,
+    "end_line": 5362,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- b\n\n  [ref]: /url\n- d\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n",
+    "example": 285,
+    "start_line": 5365,
+    "end_line": 5383,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- ```\n  b\n\n\n  ```\n- c\n",
+    "html": "<ul>\n<li>a</li>\n<li>\n<pre><code>b\n\n\n</code></pre>\n</li>\n<li>c</li>\n</ul>\n",
+    "example": 286,
+    "start_line": 5388,
+    "end_line": 5407,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  - b\n\n    c\n- d\n",
+    "html": "<ul>\n<li>a\n<ul>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n</ul>\n</li>\n<li>d</li>\n</ul>\n",
+    "example": 287,
+    "start_line": 5414,
+    "end_line": 5432,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "* a\n  > b\n  >\n* c\n",
+    "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n</li>\n<li>c</li>\n</ul>\n",
+    "example": 288,
+    "start_line": 5438,
+    "end_line": 5452,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  > b\n  ```\n  c\n  ```\n- d\n",
+    "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n<pre><code>c\n</code></pre>\n</li>\n<li>d</li>\n</ul>\n",
+    "example": 289,
+    "start_line": 5458,
+    "end_line": 5476,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n",
+    "html": "<ul>\n<li>a</li>\n</ul>\n",
+    "example": 290,
+    "start_line": 5481,
+    "end_line": 5487,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  - b\n",
+    "html": "<ul>\n<li>a\n<ul>\n<li>b</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 291,
+    "start_line": 5490,
+    "end_line": 5501,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "1. ```\n   foo\n   ```\n\n   bar\n",
+    "html": "<ol>\n<li>\n<pre><code>foo\n</code></pre>\n<p>bar</p>\n</li>\n</ol>\n",
+    "example": 292,
+    "start_line": 5507,
+    "end_line": 5521,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "* foo\n  * bar\n\n  baz\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n<p>baz</p>\n</li>\n</ul>\n",
+    "example": 293,
+    "start_line": 5526,
+    "end_line": 5541,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  - b\n  - c\n\n- d\n  - e\n  - f\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n<ul>\n<li>b</li>\n<li>c</li>\n</ul>\n</li>\n<li>\n<p>d</p>\n<ul>\n<li>e</li>\n<li>f</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 294,
+    "start_line": 5544,
+    "end_line": 5569,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "`hi`lo`\n",
+    "html": "<p><code>hi</code>lo`</p>\n",
+    "example": 295,
+    "start_line": 5578,
+    "end_line": 5582,
+    "section": "Inlines",
+    "extensions": []
+  },
+  {
+    "markdown": "\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~\n",
+    "html": "<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\\]^_`{|}~</p>\n",
+    "example": 296,
+    "start_line": 5592,
+    "end_line": 5596,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "\\\t\\A\\a\\ \\3\\\u03c6\\\u00ab\n",
+    "html": "<p>\\\t\\A\\a\\ \\3\\\u03c6\\\u00ab</p>\n",
+    "example": 297,
+    "start_line": 5602,
+    "end_line": 5606,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "\\*not emphasized*\n\\<br/> not a tag\n\\[not a link](/foo)\n\\`not code`\n1\\. not a list\n\\* not a list\n\\# not a heading\n\\[foo]: /url \"not a reference\"\n",
+    "html": "<p>*not emphasized*\n&lt;br/&gt; not a tag\n[not a link](/foo)\n`not code`\n1. not a list\n* not a list\n# not a heading\n[foo]: /url &quot;not a reference&quot;</p>\n",
+    "example": 298,
+    "start_line": 5612,
+    "end_line": 5630,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "\\\\*emphasis*\n",
+    "html": "<p>\\<em>emphasis</em></p>\n",
+    "example": 299,
+    "start_line": 5635,
+    "end_line": 5639,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\nbar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 300,
+    "start_line": 5644,
+    "end_line": 5650,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "`` \\[\\` ``\n",
+    "html": "<p><code>\\[\\`</code></p>\n",
+    "example": 301,
+    "start_line": 5656,
+    "end_line": 5660,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "    \\[\\]\n",
+    "html": "<pre><code>\\[\\]\n</code></pre>\n",
+    "example": 302,
+    "start_line": 5663,
+    "end_line": 5668,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~\n\\[\\]\n~~~\n",
+    "html": "<pre><code>\\[\\]\n</code></pre>\n",
+    "example": 303,
+    "start_line": 5671,
+    "end_line": 5678,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://example.com?find=\\*>\n",
+    "html": "<p><a href=\"http://example.com?find=%5C*\">http://example.com?find=\\*</a></p>\n",
+    "example": 304,
+    "start_line": 5681,
+    "end_line": 5685,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"/bar\\/)\">\n",
+    "html": "<a href=\"/bar\\/)\">\n",
+    "example": 305,
+    "start_line": 5688,
+    "end_line": 5692,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo](/bar\\* \"ti\\*tle\")\n",
+    "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n",
+    "example": 306,
+    "start_line": 5698,
+    "end_line": 5702,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /bar\\* \"ti\\*tle\"\n",
+    "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n",
+    "example": 307,
+    "start_line": 5705,
+    "end_line": 5711,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "``` foo\\+bar\nfoo\n```\n",
+    "html": "<pre><code class=\"language-foo+bar\">foo\n</code></pre>\n",
+    "example": 308,
+    "start_line": 5714,
+    "end_line": 5721,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "&nbsp; &amp; &copy; &AElig; &Dcaron;\n&frac34; &HilbertSpace; &DifferentialD;\n&ClockwiseContourIntegral; &ngE;\n",
+    "html": "<p>\u00a0 &amp; \u00a9 \u00c6 \u010e\n\u00be \u210b \u2146\n\u2232 \u2267\u0338</p>\n",
+    "example": 309,
+    "start_line": 5741,
+    "end_line": 5749,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&#35; &#1234; &#992; &#98765432; &#0;\n",
+    "html": "<p># \u04d2 \u03e0 \ufffd \ufffd</p>\n",
+    "example": 310,
+    "start_line": 5760,
+    "end_line": 5764,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&#X22; &#XD06; &#xcab;\n",
+    "html": "<p>&quot; \u0d06 \u0cab</p>\n",
+    "example": 311,
+    "start_line": 5773,
+    "end_line": 5777,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&nbsp &x; &#; &#x;\n&ThisIsNotDefined; &hi?;\n",
+    "html": "<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;\n&amp;ThisIsNotDefined; &amp;hi?;</p>\n",
+    "example": 312,
+    "start_line": 5782,
+    "end_line": 5788,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&copy\n",
+    "html": "<p>&amp;copy</p>\n",
+    "example": 313,
+    "start_line": 5795,
+    "end_line": 5799,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&MadeUpEntity;\n",
+    "html": "<p>&amp;MadeUpEntity;</p>\n",
+    "example": 314,
+    "start_line": 5805,
+    "end_line": 5809,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"&ouml;&ouml;.html\">\n",
+    "html": "<a href=\"&ouml;&ouml;.html\">\n",
+    "example": 315,
+    "start_line": 5816,
+    "end_line": 5820,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo](/f&ouml;&ouml; \"f&ouml;&ouml;\")\n",
+    "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"f\u00f6\u00f6\">foo</a></p>\n",
+    "example": 316,
+    "start_line": 5823,
+    "end_line": 5827,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /f&ouml;&ouml; \"f&ouml;&ouml;\"\n",
+    "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"f\u00f6\u00f6\">foo</a></p>\n",
+    "example": 317,
+    "start_line": 5830,
+    "end_line": 5836,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "``` f&ouml;&ouml;\nfoo\n```\n",
+    "html": "<pre><code class=\"language-f\u00f6\u00f6\">foo\n</code></pre>\n",
+    "example": 318,
+    "start_line": 5839,
+    "end_line": 5846,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "`f&ouml;&ouml;`\n",
+    "html": "<p><code>f&amp;ouml;&amp;ouml;</code></p>\n",
+    "example": 319,
+    "start_line": 5852,
+    "end_line": 5856,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "    f&ouml;f&ouml;\n",
+    "html": "<pre><code>f&amp;ouml;f&amp;ouml;\n</code></pre>\n",
+    "example": 320,
+    "start_line": 5859,
+    "end_line": 5864,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo`\n",
+    "html": "<p><code>foo</code></p>\n",
+    "example": 321,
+    "start_line": 5881,
+    "end_line": 5885,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`` foo ` bar  ``\n",
+    "html": "<p><code>foo ` bar</code></p>\n",
+    "example": 322,
+    "start_line": 5891,
+    "end_line": 5895,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "` `` `\n",
+    "html": "<p><code>``</code></p>\n",
+    "example": 323,
+    "start_line": 5901,
+    "end_line": 5905,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "``\nfoo\n``\n",
+    "html": "<p><code>foo</code></p>\n",
+    "example": 324,
+    "start_line": 5910,
+    "end_line": 5916,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo   bar\n  baz`\n",
+    "html": "<p><code>foo bar baz</code></p>\n",
+    "example": 325,
+    "start_line": 5922,
+    "end_line": 5927,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`a\u00a0\u00a0b`\n",
+    "html": "<p><code>a\u00a0\u00a0b</code></p>\n",
+    "example": 326,
+    "start_line": 5933,
+    "end_line": 5937,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo `` bar`\n",
+    "html": "<p><code>foo `` bar</code></p>\n",
+    "example": 327,
+    "start_line": 5953,
+    "end_line": 5957,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo\\`bar`\n",
+    "html": "<p><code>foo\\</code>bar`</p>\n",
+    "example": 328,
+    "start_line": 5963,
+    "end_line": 5967,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo`*`\n",
+    "html": "<p>*foo<code>*</code></p>\n",
+    "example": 329,
+    "start_line": 5979,
+    "end_line": 5983,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "[not a `link](/foo`)\n",
+    "html": "<p>[not a <code>link](/foo</code>)</p>\n",
+    "example": 330,
+    "start_line": 5988,
+    "end_line": 5992,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`<a href=\"`\">`\n",
+    "html": "<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>\n",
+    "example": 331,
+    "start_line": 5998,
+    "end_line": 6002,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"`\">`\n",
+    "html": "<p><a href=\"`\">`</p>\n",
+    "example": 332,
+    "start_line": 6007,
+    "end_line": 6011,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`<http://foo.bar.`baz>`\n",
+    "html": "<p><code>&lt;http://foo.bar.</code>baz&gt;`</p>\n",
+    "example": 333,
+    "start_line": 6016,
+    "end_line": 6020,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar.`baz>`\n",
+    "html": "<p><a href=\"http://foo.bar.%60baz\">http://foo.bar.`baz</a>`</p>\n",
+    "example": 334,
+    "start_line": 6025,
+    "end_line": 6029,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "```foo``\n",
+    "html": "<p>```foo``</p>\n",
+    "example": 335,
+    "start_line": 6035,
+    "end_line": 6039,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo\n",
+    "html": "<p>`foo</p>\n",
+    "example": 336,
+    "start_line": 6042,
+    "end_line": 6046,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo bar*\n",
+    "html": "<p><em>foo bar</em></p>\n",
+    "example": 337,
+    "start_line": 6254,
+    "end_line": 6258,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a * foo bar*\n",
+    "html": "<p>a * foo bar*</p>\n",
+    "example": 338,
+    "start_line": 6264,
+    "end_line": 6268,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a*\"foo\"*\n",
+    "html": "<p>a*&quot;foo&quot;*</p>\n",
+    "example": 339,
+    "start_line": 6275,
+    "end_line": 6279,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*\u00a0a\u00a0*\n",
+    "html": "<p>*\u00a0a\u00a0*</p>\n",
+    "example": 340,
+    "start_line": 6284,
+    "end_line": 6288,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo*bar*\n",
+    "html": "<p>foo<em>bar</em></p>\n",
+    "example": 341,
+    "start_line": 6293,
+    "end_line": 6297,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "5*6*78\n",
+    "html": "<p>5<em>6</em>78</p>\n",
+    "example": 342,
+    "start_line": 6300,
+    "end_line": 6304,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo bar_\n",
+    "html": "<p><em>foo bar</em></p>\n",
+    "example": 343,
+    "start_line": 6309,
+    "end_line": 6313,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_ foo bar_\n",
+    "html": "<p>_ foo bar_</p>\n",
+    "example": 344,
+    "start_line": 6319,
+    "end_line": 6323,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a_\"foo\"_\n",
+    "html": "<p>a_&quot;foo&quot;_</p>\n",
+    "example": 345,
+    "start_line": 6329,
+    "end_line": 6333,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo_bar_\n",
+    "html": "<p>foo_bar_</p>\n",
+    "example": 346,
+    "start_line": 6338,
+    "end_line": 6342,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "5_6_78\n",
+    "html": "<p>5_6_78</p>\n",
+    "example": 347,
+    "start_line": 6345,
+    "end_line": 6349,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f_\n",
+    "html": "<p>\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f_</p>\n",
+    "example": 348,
+    "start_line": 6352,
+    "end_line": 6356,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "aa_\"bb\"_cc\n",
+    "html": "<p>aa_&quot;bb&quot;_cc</p>\n",
+    "example": 349,
+    "start_line": 6362,
+    "end_line": 6366,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo-_(bar)_\n",
+    "html": "<p>foo-<em>(bar)</em></p>\n",
+    "example": 350,
+    "start_line": 6373,
+    "end_line": 6377,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo*\n",
+    "html": "<p>_foo*</p>\n",
+    "example": 351,
+    "start_line": 6385,
+    "end_line": 6389,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo bar *\n",
+    "html": "<p>*foo bar *</p>\n",
+    "example": 352,
+    "start_line": 6395,
+    "end_line": 6399,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo bar\n*\n",
+    "html": "<p>*foo bar\n*</p>\n",
+    "example": 353,
+    "start_line": 6404,
+    "end_line": 6410,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*(*foo)\n",
+    "html": "<p>*(*foo)</p>\n",
+    "example": 354,
+    "start_line": 6417,
+    "end_line": 6421,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*(*foo*)*\n",
+    "html": "<p><em>(<em>foo</em>)</em></p>\n",
+    "example": 355,
+    "start_line": 6427,
+    "end_line": 6431,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo*bar\n",
+    "html": "<p><em>foo</em>bar</p>\n",
+    "example": 356,
+    "start_line": 6436,
+    "end_line": 6440,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo bar _\n",
+    "html": "<p>_foo bar _</p>\n",
+    "example": 357,
+    "start_line": 6449,
+    "end_line": 6453,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(_foo)\n",
+    "html": "<p>_(_foo)</p>\n",
+    "example": 358,
+    "start_line": 6459,
+    "end_line": 6463,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(_foo_)_\n",
+    "html": "<p><em>(<em>foo</em>)</em></p>\n",
+    "example": 359,
+    "start_line": 6468,
+    "end_line": 6472,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo_bar\n",
+    "html": "<p>_foo_bar</p>\n",
+    "example": 360,
+    "start_line": 6477,
+    "end_line": 6481,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f\n",
+    "html": "<p>_\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f</p>\n",
+    "example": 361,
+    "start_line": 6484,
+    "end_line": 6488,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo_bar_baz_\n",
+    "html": "<p><em>foo_bar_baz</em></p>\n",
+    "example": 362,
+    "start_line": 6491,
+    "end_line": 6495,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(bar)_.\n",
+    "html": "<p><em>(bar)</em>.</p>\n",
+    "example": 363,
+    "start_line": 6502,
+    "end_line": 6506,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo bar**\n",
+    "html": "<p><strong>foo bar</strong></p>\n",
+    "example": 364,
+    "start_line": 6511,
+    "end_line": 6515,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "** foo bar**\n",
+    "html": "<p>** foo bar**</p>\n",
+    "example": 365,
+    "start_line": 6521,
+    "end_line": 6525,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a**\"foo\"**\n",
+    "html": "<p>a**&quot;foo&quot;**</p>\n",
+    "example": 366,
+    "start_line": 6532,
+    "end_line": 6536,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo**bar**\n",
+    "html": "<p>foo<strong>bar</strong></p>\n",
+    "example": 367,
+    "start_line": 6541,
+    "end_line": 6545,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo bar__\n",
+    "html": "<p><strong>foo bar</strong></p>\n",
+    "example": 368,
+    "start_line": 6550,
+    "end_line": 6554,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__ foo bar__\n",
+    "html": "<p>__ foo bar__</p>\n",
+    "example": 369,
+    "start_line": 6560,
+    "end_line": 6564,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__\nfoo bar__\n",
+    "html": "<p>__\nfoo bar__</p>\n",
+    "example": 370,
+    "start_line": 6568,
+    "end_line": 6574,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a__\"foo\"__\n",
+    "html": "<p>a__&quot;foo&quot;__</p>\n",
+    "example": 371,
+    "start_line": 6580,
+    "end_line": 6584,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo__bar__\n",
+    "html": "<p>foo__bar__</p>\n",
+    "example": 372,
+    "start_line": 6589,
+    "end_line": 6593,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "5__6__78\n",
+    "html": "<p>5__6__78</p>\n",
+    "example": 373,
+    "start_line": 6596,
+    "end_line": 6600,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f__\n",
+    "html": "<p>\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f__</p>\n",
+    "example": 374,
+    "start_line": 6603,
+    "end_line": 6607,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo, __bar__, baz__\n",
+    "html": "<p><strong>foo, <strong>bar</strong>, baz</strong></p>\n",
+    "example": 375,
+    "start_line": 6610,
+    "end_line": 6614,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo-__(bar)__\n",
+    "html": "<p>foo-<strong>(bar)</strong></p>\n",
+    "example": 376,
+    "start_line": 6621,
+    "end_line": 6625,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo bar **\n",
+    "html": "<p>**foo bar **</p>\n",
+    "example": 377,
+    "start_line": 6634,
+    "end_line": 6638,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**(**foo)\n",
+    "html": "<p>**(**foo)</p>\n",
+    "example": 378,
+    "start_line": 6647,
+    "end_line": 6651,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*(**foo**)*\n",
+    "html": "<p><em>(<strong>foo</strong>)</em></p>\n",
+    "example": 379,
+    "start_line": 6657,
+    "end_line": 6661,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**Gomphocarpus (*Gomphocarpus physocarpus*, syn.\n*Asclepias physocarpa*)**\n",
+    "html": "<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.\n<em>Asclepias physocarpa</em>)</strong></p>\n",
+    "example": 380,
+    "start_line": 6664,
+    "end_line": 6670,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo \"*bar*\" foo**\n",
+    "html": "<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>\n",
+    "example": 381,
+    "start_line": 6673,
+    "end_line": 6677,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo**bar\n",
+    "html": "<p><strong>foo</strong>bar</p>\n",
+    "example": 382,
+    "start_line": 6682,
+    "end_line": 6686,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo bar __\n",
+    "html": "<p>__foo bar __</p>\n",
+    "example": 383,
+    "start_line": 6694,
+    "end_line": 6698,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__(__foo)\n",
+    "html": "<p>__(__foo)</p>\n",
+    "example": 384,
+    "start_line": 6704,
+    "end_line": 6708,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(__foo__)_\n",
+    "html": "<p><em>(<strong>foo</strong>)</em></p>\n",
+    "example": 385,
+    "start_line": 6714,
+    "end_line": 6718,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo__bar\n",
+    "html": "<p>__foo__bar</p>\n",
+    "example": 386,
+    "start_line": 6723,
+    "end_line": 6727,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f\n",
+    "html": "<p>__\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f</p>\n",
+    "example": 387,
+    "start_line": 6730,
+    "end_line": 6734,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo__bar__baz__\n",
+    "html": "<p><strong>foo__bar__baz</strong></p>\n",
+    "example": 388,
+    "start_line": 6737,
+    "end_line": 6741,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__(bar)__.\n",
+    "html": "<p><strong>(bar)</strong>.</p>\n",
+    "example": 389,
+    "start_line": 6748,
+    "end_line": 6752,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo [bar](/url)*\n",
+    "html": "<p><em>foo <a href=\"/url\">bar</a></em></p>\n",
+    "example": 390,
+    "start_line": 6760,
+    "end_line": 6764,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo\nbar*\n",
+    "html": "<p><em>foo\nbar</em></p>\n",
+    "example": 391,
+    "start_line": 6767,
+    "end_line": 6773,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo __bar__ baz_\n",
+    "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n",
+    "example": 392,
+    "start_line": 6779,
+    "end_line": 6783,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo _bar_ baz_\n",
+    "html": "<p><em>foo <em>bar</em> baz</em></p>\n",
+    "example": 393,
+    "start_line": 6786,
+    "end_line": 6790,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo_ bar_\n",
+    "html": "<p><em><em>foo</em> bar</em></p>\n",
+    "example": 394,
+    "start_line": 6793,
+    "end_line": 6797,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo *bar**\n",
+    "html": "<p><em>foo <em>bar</em></em></p>\n",
+    "example": 395,
+    "start_line": 6800,
+    "end_line": 6804,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo **bar** baz*\n",
+    "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n",
+    "example": 396,
+    "start_line": 6807,
+    "end_line": 6811,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo**bar**baz*\n",
+    "html": "<p><em>foo<strong>bar</strong>baz</em></p>\n",
+    "example": 397,
+    "start_line": 6813,
+    "end_line": 6817,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo** bar*\n",
+    "html": "<p><em><strong>foo</strong> bar</em></p>\n",
+    "example": 398,
+    "start_line": 6838,
+    "end_line": 6842,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo **bar***\n",
+    "html": "<p><em>foo <strong>bar</strong></em></p>\n",
+    "example": 399,
+    "start_line": 6845,
+    "end_line": 6849,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo**bar***\n",
+    "html": "<p><em>foo<strong>bar</strong></em></p>\n",
+    "example": 400,
+    "start_line": 6852,
+    "end_line": 6856,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo **bar *baz* bim** bop*\n",
+    "html": "<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>\n",
+    "example": 401,
+    "start_line": 6861,
+    "end_line": 6865,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo [*bar*](/url)*\n",
+    "html": "<p><em>foo <a href=\"/url\"><em>bar</em></a></em></p>\n",
+    "example": 402,
+    "start_line": 6868,
+    "end_line": 6872,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "** is not an empty emphasis\n",
+    "html": "<p>** is not an empty emphasis</p>\n",
+    "example": 403,
+    "start_line": 6877,
+    "end_line": 6881,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**** is not an empty strong emphasis\n",
+    "html": "<p>**** is not an empty strong emphasis</p>\n",
+    "example": 404,
+    "start_line": 6884,
+    "end_line": 6888,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo [bar](/url)**\n",
+    "html": "<p><strong>foo <a href=\"/url\">bar</a></strong></p>\n",
+    "example": 405,
+    "start_line": 6897,
+    "end_line": 6901,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo\nbar**\n",
+    "html": "<p><strong>foo\nbar</strong></p>\n",
+    "example": 406,
+    "start_line": 6904,
+    "end_line": 6910,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo _bar_ baz__\n",
+    "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n",
+    "example": 407,
+    "start_line": 6916,
+    "end_line": 6920,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo __bar__ baz__\n",
+    "html": "<p><strong>foo <strong>bar</strong> baz</strong></p>\n",
+    "example": 408,
+    "start_line": 6923,
+    "end_line": 6927,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____foo__ bar__\n",
+    "html": "<p><strong><strong>foo</strong> bar</strong></p>\n",
+    "example": 409,
+    "start_line": 6930,
+    "end_line": 6934,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo **bar****\n",
+    "html": "<p><strong>foo <strong>bar</strong></strong></p>\n",
+    "example": 410,
+    "start_line": 6937,
+    "end_line": 6941,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo *bar* baz**\n",
+    "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n",
+    "example": 411,
+    "start_line": 6944,
+    "end_line": 6948,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo*bar*baz**\n",
+    "html": "<p><strong>foo<em>bar</em>baz</strong></p>\n",
+    "example": 412,
+    "start_line": 6951,
+    "end_line": 6955,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo* bar**\n",
+    "html": "<p><strong><em>foo</em> bar</strong></p>\n",
+    "example": 413,
+    "start_line": 6958,
+    "end_line": 6962,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo *bar***\n",
+    "html": "<p><strong>foo <em>bar</em></strong></p>\n",
+    "example": 414,
+    "start_line": 6965,
+    "end_line": 6969,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo *bar **baz**\nbim* bop**\n",
+    "html": "<p><strong>foo <em>bar <strong>baz</strong>\nbim</em> bop</strong></p>\n",
+    "example": 415,
+    "start_line": 6974,
+    "end_line": 6980,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo [*bar*](/url)**\n",
+    "html": "<p><strong>foo <a href=\"/url\"><em>bar</em></a></strong></p>\n",
+    "example": 416,
+    "start_line": 6983,
+    "end_line": 6987,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__ is not an empty emphasis\n",
+    "html": "<p>__ is not an empty emphasis</p>\n",
+    "example": 417,
+    "start_line": 6992,
+    "end_line": 6996,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____ is not an empty strong emphasis\n",
+    "html": "<p>____ is not an empty strong emphasis</p>\n",
+    "example": 418,
+    "start_line": 6999,
+    "end_line": 7003,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo ***\n",
+    "html": "<p>foo ***</p>\n",
+    "example": 419,
+    "start_line": 7009,
+    "end_line": 7013,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo *\\**\n",
+    "html": "<p>foo <em>*</em></p>\n",
+    "example": 420,
+    "start_line": 7016,
+    "end_line": 7020,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo *_*\n",
+    "html": "<p>foo <em>_</em></p>\n",
+    "example": 421,
+    "start_line": 7023,
+    "end_line": 7027,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo *****\n",
+    "html": "<p>foo *****</p>\n",
+    "example": 422,
+    "start_line": 7030,
+    "end_line": 7034,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo **\\***\n",
+    "html": "<p>foo <strong>*</strong></p>\n",
+    "example": 423,
+    "start_line": 7037,
+    "end_line": 7041,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo **_**\n",
+    "html": "<p>foo <strong>_</strong></p>\n",
+    "example": 424,
+    "start_line": 7044,
+    "end_line": 7048,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo*\n",
+    "html": "<p>*<em>foo</em></p>\n",
+    "example": 425,
+    "start_line": 7055,
+    "end_line": 7059,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo**\n",
+    "html": "<p><em>foo</em>*</p>\n",
+    "example": 426,
+    "start_line": 7062,
+    "end_line": 7066,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo**\n",
+    "html": "<p>*<strong>foo</strong></p>\n",
+    "example": 427,
+    "start_line": 7069,
+    "end_line": 7073,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "****foo*\n",
+    "html": "<p>***<em>foo</em></p>\n",
+    "example": 428,
+    "start_line": 7076,
+    "end_line": 7080,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo***\n",
+    "html": "<p><strong>foo</strong>*</p>\n",
+    "example": 429,
+    "start_line": 7083,
+    "end_line": 7087,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo****\n",
+    "html": "<p><em>foo</em>***</p>\n",
+    "example": 430,
+    "start_line": 7090,
+    "end_line": 7094,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo ___\n",
+    "html": "<p>foo ___</p>\n",
+    "example": 431,
+    "start_line": 7100,
+    "end_line": 7104,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo _\\__\n",
+    "html": "<p>foo <em>_</em></p>\n",
+    "example": 432,
+    "start_line": 7107,
+    "end_line": 7111,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo _*_\n",
+    "html": "<p>foo <em>*</em></p>\n",
+    "example": 433,
+    "start_line": 7114,
+    "end_line": 7118,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo _____\n",
+    "html": "<p>foo _____</p>\n",
+    "example": 434,
+    "start_line": 7121,
+    "end_line": 7125,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo __\\___\n",
+    "html": "<p>foo <strong>_</strong></p>\n",
+    "example": 435,
+    "start_line": 7128,
+    "end_line": 7132,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo __*__\n",
+    "html": "<p>foo <strong>*</strong></p>\n",
+    "example": 436,
+    "start_line": 7135,
+    "end_line": 7139,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo_\n",
+    "html": "<p>_<em>foo</em></p>\n",
+    "example": 437,
+    "start_line": 7142,
+    "end_line": 7146,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo__\n",
+    "html": "<p><em>foo</em>_</p>\n",
+    "example": 438,
+    "start_line": 7153,
+    "end_line": 7157,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "___foo__\n",
+    "html": "<p>_<strong>foo</strong></p>\n",
+    "example": 439,
+    "start_line": 7160,
+    "end_line": 7164,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____foo_\n",
+    "html": "<p>___<em>foo</em></p>\n",
+    "example": 440,
+    "start_line": 7167,
+    "end_line": 7171,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo___\n",
+    "html": "<p><strong>foo</strong>_</p>\n",
+    "example": 441,
+    "start_line": 7174,
+    "end_line": 7178,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo____\n",
+    "html": "<p><em>foo</em>___</p>\n",
+    "example": 442,
+    "start_line": 7181,
+    "end_line": 7185,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo**\n",
+    "html": "<p><strong>foo</strong></p>\n",
+    "example": 443,
+    "start_line": 7191,
+    "end_line": 7195,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*_foo_*\n",
+    "html": "<p><em><em>foo</em></em></p>\n",
+    "example": 444,
+    "start_line": 7198,
+    "end_line": 7202,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo__\n",
+    "html": "<p><strong>foo</strong></p>\n",
+    "example": 445,
+    "start_line": 7205,
+    "end_line": 7209,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_*foo*_\n",
+    "html": "<p><em><em>foo</em></em></p>\n",
+    "example": 446,
+    "start_line": 7212,
+    "end_line": 7216,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "****foo****\n",
+    "html": "<p><strong><strong>foo</strong></strong></p>\n",
+    "example": 447,
+    "start_line": 7222,
+    "end_line": 7226,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____foo____\n",
+    "html": "<p><strong><strong>foo</strong></strong></p>\n",
+    "example": 448,
+    "start_line": 7229,
+    "end_line": 7233,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "******foo******\n",
+    "html": "<p><strong><strong><strong>foo</strong></strong></strong></p>\n",
+    "example": 449,
+    "start_line": 7240,
+    "end_line": 7244,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo***\n",
+    "html": "<p><em><strong>foo</strong></em></p>\n",
+    "example": 450,
+    "start_line": 7249,
+    "end_line": 7253,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_____foo_____\n",
+    "html": "<p><em><strong><strong>foo</strong></strong></em></p>\n",
+    "example": 451,
+    "start_line": 7256,
+    "end_line": 7260,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo _bar* baz_\n",
+    "html": "<p><em>foo _bar</em> baz_</p>\n",
+    "example": 452,
+    "start_line": 7265,
+    "end_line": 7269,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo __bar *baz bim__ bam*\n",
+    "html": "<p><em>foo <strong>bar *baz bim</strong> bam</em></p>\n",
+    "example": 453,
+    "start_line": 7272,
+    "end_line": 7276,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo **bar baz**\n",
+    "html": "<p>**foo <strong>bar baz</strong></p>\n",
+    "example": 454,
+    "start_line": 7281,
+    "end_line": 7285,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo *bar baz*\n",
+    "html": "<p>*foo <em>bar baz</em></p>\n",
+    "example": 455,
+    "start_line": 7288,
+    "end_line": 7292,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*[bar*](/url)\n",
+    "html": "<p>*<a href=\"/url\">bar*</a></p>\n",
+    "example": 456,
+    "start_line": 7297,
+    "end_line": 7301,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo [bar_](/url)\n",
+    "html": "<p>_foo <a href=\"/url\">bar_</a></p>\n",
+    "example": 457,
+    "start_line": 7304,
+    "end_line": 7308,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*<img src=\"foo\" title=\"*\"/>\n",
+    "html": "<p>*<img src=\"foo\" title=\"*\"/></p>\n",
+    "example": 458,
+    "start_line": 7311,
+    "end_line": 7315,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**<a href=\"**\">\n",
+    "html": "<p>**<a href=\"**\"></p>\n",
+    "example": 459,
+    "start_line": 7318,
+    "end_line": 7322,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__<a href=\"__\">\n",
+    "html": "<p>__<a href=\"__\"></p>\n",
+    "example": 460,
+    "start_line": 7325,
+    "end_line": 7329,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*a `*`*\n",
+    "html": "<p><em>a <code>*</code></em></p>\n",
+    "example": 461,
+    "start_line": 7332,
+    "end_line": 7336,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_a `_`_\n",
+    "html": "<p><em>a <code>_</code></em></p>\n",
+    "example": 462,
+    "start_line": 7339,
+    "end_line": 7343,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**a<http://foo.bar/?q=**>\n",
+    "html": "<p>**a<a href=\"http://foo.bar/?q=**\">http://foo.bar/?q=**</a></p>\n",
+    "example": 463,
+    "start_line": 7346,
+    "end_line": 7350,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__a<http://foo.bar/?q=__>\n",
+    "html": "<p>__a<a href=\"http://foo.bar/?q=__\">http://foo.bar/?q=__</a></p>\n",
+    "example": 464,
+    "start_line": 7353,
+    "end_line": 7357,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "~Hi~ Hello, world!\n",
+    "html": "<p><del>Hi</del> Hello, world!</p>\n",
+    "example": 465,
+    "start_line": 7369,
+    "end_line": 7373,
+    "section": "Strikethrough (extension)",
+    "extensions": [
+      "strikethrough"
+    ]
+  },
+  {
+    "markdown": "This ~text~~~~ is ~~~~curious~.\n",
+    "html": "<p>This <del>text</del> is <del>curious</del>.</p>\n",
+    "example": 466,
+    "start_line": 7378,
+    "end_line": 7382,
+    "section": "Strikethrough (extension)",
+    "extensions": [
+      "strikethrough"
+    ]
+  },
+  {
+    "markdown": "This ~~has a\n\nnew paragraph~~.\n",
+    "html": "<p>This ~~has a</p>\n<p>new paragraph~~.</p>\n",
+    "example": 467,
+    "start_line": 7387,
+    "end_line": 7394,
+    "section": "Strikethrough (extension)",
+    "extensions": [
+      "strikethrough"
+    ]
+  },
+  {
+    "markdown": "[link](/uri \"title\")\n",
+    "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n",
+    "example": 468,
+    "start_line": 7469,
+    "end_line": 7473,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/uri)\n",
+    "html": "<p><a href=\"/uri\">link</a></p>\n",
+    "example": 469,
+    "start_line": 7478,
+    "end_line": 7482,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link]()\n",
+    "html": "<p><a href=\"\">link</a></p>\n",
+    "example": 470,
+    "start_line": 7487,
+    "end_line": 7491,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](<>)\n",
+    "html": "<p><a href=\"\">link</a></p>\n",
+    "example": 471,
+    "start_line": 7494,
+    "end_line": 7498,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/my uri)\n",
+    "html": "<p>[link](/my uri)</p>\n",
+    "example": 472,
+    "start_line": 7504,
+    "end_line": 7508,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](</my uri>)\n",
+    "html": "<p>[link](&lt;/my uri&gt;)</p>\n",
+    "example": 473,
+    "start_line": 7511,
+    "end_line": 7515,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\nbar)\n",
+    "html": "<p>[link](foo\nbar)</p>\n",
+    "example": 474,
+    "start_line": 7518,
+    "end_line": 7524,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](<foo\nbar>)\n",
+    "html": "<p>[link](<foo\nbar>)</p>\n",
+    "example": 475,
+    "start_line": 7527,
+    "end_line": 7533,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](\\(foo\\))\n",
+    "html": "<p><a href=\"(foo)\">link</a></p>\n",
+    "example": 476,
+    "start_line": 7537,
+    "end_line": 7541,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo(and(bar)))\n",
+    "html": "<p><a href=\"foo(and(bar))\">link</a></p>\n",
+    "example": 477,
+    "start_line": 7546,
+    "end_line": 7550,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\\(and\\(bar\\))\n",
+    "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n",
+    "example": 478,
+    "start_line": 7555,
+    "end_line": 7559,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](<foo(and(bar)>)\n",
+    "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n",
+    "example": 479,
+    "start_line": 7562,
+    "end_line": 7566,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\\)\\:)\n",
+    "html": "<p><a href=\"foo):\">link</a></p>\n",
+    "example": 480,
+    "start_line": 7572,
+    "end_line": 7576,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](#fragment)\n\n[link](http://example.com#fragment)\n\n[link](http://example.com?foo=3#frag)\n",
+    "html": "<p><a href=\"#fragment\">link</a></p>\n<p><a href=\"http://example.com#fragment\">link</a></p>\n<p><a href=\"http://example.com?foo=3#frag\">link</a></p>\n",
+    "example": 481,
+    "start_line": 7581,
+    "end_line": 7591,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\\bar)\n",
+    "html": "<p><a href=\"foo%5Cbar\">link</a></p>\n",
+    "example": 482,
+    "start_line": 7597,
+    "end_line": 7601,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo%20b&auml;)\n",
+    "html": "<p><a href=\"foo%20b%C3%A4\">link</a></p>\n",
+    "example": 483,
+    "start_line": 7613,
+    "end_line": 7617,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](\"title\")\n",
+    "html": "<p><a href=\"%22title%22\">link</a></p>\n",
+    "example": 484,
+    "start_line": 7624,
+    "end_line": 7628,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url \"title\")\n[link](/url 'title')\n[link](/url (title))\n",
+    "html": "<p><a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a></p>\n",
+    "example": 485,
+    "start_line": 7633,
+    "end_line": 7641,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url \"title \\\"&quot;\")\n",
+    "html": "<p><a href=\"/url\" title=\"title &quot;&quot;\">link</a></p>\n",
+    "example": 486,
+    "start_line": 7647,
+    "end_line": 7651,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url\u00a0\"title\")\n",
+    "html": "<p><a href=\"/url%C2%A0%22title%22\">link</a></p>\n",
+    "example": 487,
+    "start_line": 7657,
+    "end_line": 7661,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url \"title \"and\" title\")\n",
+    "html": "<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>\n",
+    "example": 488,
+    "start_line": 7666,
+    "end_line": 7670,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url 'title \"and\" title')\n",
+    "html": "<p><a href=\"/url\" title=\"title &quot;and&quot; title\">link</a></p>\n",
+    "example": 489,
+    "start_line": 7675,
+    "end_line": 7679,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](   /uri\n  \"title\"  )\n",
+    "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n",
+    "example": 490,
+    "start_line": 7699,
+    "end_line": 7704,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link] (/uri)\n",
+    "html": "<p>[link] (/uri)</p>\n",
+    "example": 491,
+    "start_line": 7710,
+    "end_line": 7714,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link [foo [bar]]](/uri)\n",
+    "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n",
+    "example": 492,
+    "start_line": 7720,
+    "end_line": 7724,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link] bar](/uri)\n",
+    "html": "<p>[link] bar](/uri)</p>\n",
+    "example": 493,
+    "start_line": 7727,
+    "end_line": 7731,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link [bar](/uri)\n",
+    "html": "<p>[link <a href=\"/uri\">bar</a></p>\n",
+    "example": 494,
+    "start_line": 7734,
+    "end_line": 7738,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link \\[bar](/uri)\n",
+    "html": "<p><a href=\"/uri\">link [bar</a></p>\n",
+    "example": 495,
+    "start_line": 7741,
+    "end_line": 7745,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link *foo **bar** `#`*](/uri)\n",
+    "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n",
+    "example": 496,
+    "start_line": 7750,
+    "end_line": 7754,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[![moon](moon.jpg)](/uri)\n",
+    "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n",
+    "example": 497,
+    "start_line": 7757,
+    "end_line": 7761,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo [bar](/uri)](/uri)\n",
+    "html": "<p>[foo <a href=\"/uri\">bar</a>](/uri)</p>\n",
+    "example": 498,
+    "start_line": 7766,
+    "end_line": 7770,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *[bar [baz](/uri)](/uri)*](/uri)\n",
+    "html": "<p>[foo <em>[bar <a href=\"/uri\">baz</a>](/uri)</em>](/uri)</p>\n",
+    "example": 499,
+    "start_line": 7773,
+    "end_line": 7777,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "![[[foo](uri1)](uri2)](uri3)\n",
+    "html": "<p><img src=\"uri3\" alt=\"[foo](uri2)\" /></p>\n",
+    "example": 500,
+    "start_line": 7780,
+    "end_line": 7784,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "*[foo*](/uri)\n",
+    "html": "<p>*<a href=\"/uri\">foo*</a></p>\n",
+    "example": 501,
+    "start_line": 7790,
+    "end_line": 7794,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *bar](baz*)\n",
+    "html": "<p><a href=\"baz*\">foo *bar</a></p>\n",
+    "example": 502,
+    "start_line": 7797,
+    "end_line": 7801,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo [bar* baz]\n",
+    "html": "<p><em>foo [bar</em> baz]</p>\n",
+    "example": 503,
+    "start_line": 7807,
+    "end_line": 7811,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo <bar attr=\"](baz)\">\n",
+    "html": "<p>[foo <bar attr=\"](baz)\"></p>\n",
+    "example": 504,
+    "start_line": 7817,
+    "end_line": 7821,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo`](/uri)`\n",
+    "html": "<p>[foo<code>](/uri)</code></p>\n",
+    "example": 505,
+    "start_line": 7824,
+    "end_line": 7828,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo<http://example.com/?search=](uri)>\n",
+    "html": "<p>[foo<a href=\"http://example.com/?search=%5D(uri)\">http://example.com/?search=](uri)</a></p>\n",
+    "example": 506,
+    "start_line": 7831,
+    "end_line": 7835,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 507,
+    "start_line": 7866,
+    "end_line": 7872,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link [foo [bar]]][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n",
+    "example": 508,
+    "start_line": 7881,
+    "end_line": 7887,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link \\[bar][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link [bar</a></p>\n",
+    "example": 509,
+    "start_line": 7890,
+    "end_line": 7896,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link *foo **bar** `#`*][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n",
+    "example": 510,
+    "start_line": 7901,
+    "end_line": 7907,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[![moon](moon.jpg)][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n",
+    "example": 511,
+    "start_line": 7910,
+    "end_line": 7916,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo [bar](/uri)][ref]\n\n[ref]: /uri\n",
+    "html": "<p>[foo <a href=\"/uri\">bar</a>]<a href=\"/uri\">ref</a></p>\n",
+    "example": 512,
+    "start_line": 7921,
+    "end_line": 7927,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *bar [baz][ref]*][ref]\n\n[ref]: /uri\n",
+    "html": "<p>[foo <em>bar <a href=\"/uri\">baz</a></em>]<a href=\"/uri\">ref</a></p>\n",
+    "example": 513,
+    "start_line": 7930,
+    "end_line": 7936,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "*[foo*][ref]\n\n[ref]: /uri\n",
+    "html": "<p>*<a href=\"/uri\">foo*</a></p>\n",
+    "example": 514,
+    "start_line": 7945,
+    "end_line": 7951,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *bar][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">foo *bar</a></p>\n",
+    "example": 515,
+    "start_line": 7954,
+    "end_line": 7960,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo <bar attr=\"][ref]\">\n\n[ref]: /uri\n",
+    "html": "<p>[foo <bar attr=\"][ref]\"></p>\n",
+    "example": 516,
+    "start_line": 7966,
+    "end_line": 7972,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo`][ref]`\n\n[ref]: /uri\n",
+    "html": "<p>[foo<code>][ref]</code></p>\n",
+    "example": 517,
+    "start_line": 7975,
+    "end_line": 7981,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo<http://example.com/?search=][ref]>\n\n[ref]: /uri\n",
+    "html": "<p>[foo<a href=\"http://example.com/?search=%5D%5Bref%5D\">http://example.com/?search=][ref]</a></p>\n",
+    "example": 518,
+    "start_line": 7984,
+    "end_line": 7990,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][BaR]\n\n[bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 519,
+    "start_line": 7995,
+    "end_line": 8001,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[\u0422\u043e\u043b\u043f\u043e\u0439][\u0422\u043e\u043b\u043f\u043e\u0439] is a Russian word.\n\n[\u0422\u041e\u041b\u041f\u041e\u0419]: /url\n",
+    "html": "<p><a href=\"/url\">\u0422\u043e\u043b\u043f\u043e\u0439</a> is a Russian word.</p>\n",
+    "example": 520,
+    "start_line": 8006,
+    "end_line": 8012,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo\n  bar]: /url\n\n[Baz][Foo bar]\n",
+    "html": "<p><a href=\"/url\">Baz</a></p>\n",
+    "example": 521,
+    "start_line": 8018,
+    "end_line": 8025,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo] [bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p>[foo] <a href=\"/url\" title=\"title\">bar</a></p>\n",
+    "example": 522,
+    "start_line": 8031,
+    "end_line": 8037,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n[bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p>[foo]\n<a href=\"/url\" title=\"title\">bar</a></p>\n",
+    "example": 523,
+    "start_line": 8040,
+    "end_line": 8048,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url1\n\n[foo]: /url2\n\n[bar][foo]\n",
+    "html": "<p><a href=\"/url1\">bar</a></p>\n",
+    "example": 524,
+    "start_line": 8081,
+    "end_line": 8089,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[bar][foo\\!]\n\n[foo!]: /url\n",
+    "html": "<p>[bar][foo!]</p>\n",
+    "example": 525,
+    "start_line": 8096,
+    "end_line": 8102,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][ref[]\n\n[ref[]: /uri\n",
+    "html": "<p>[foo][ref[]</p>\n<p>[ref[]: /uri</p>\n",
+    "example": 526,
+    "start_line": 8108,
+    "end_line": 8115,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][ref[bar]]\n\n[ref[bar]]: /uri\n",
+    "html": "<p>[foo][ref[bar]]</p>\n<p>[ref[bar]]: /uri</p>\n",
+    "example": 527,
+    "start_line": 8118,
+    "end_line": 8125,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[[[foo]]]\n\n[[[foo]]]: /url\n",
+    "html": "<p>[[[foo]]]</p>\n<p>[[[foo]]]: /url</p>\n",
+    "example": 528,
+    "start_line": 8128,
+    "end_line": 8135,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][ref\\[]\n\n[ref\\[]: /uri\n",
+    "html": "<p><a href=\"/uri\">foo</a></p>\n",
+    "example": 529,
+    "start_line": 8138,
+    "end_line": 8144,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[bar\\\\]: /uri\n\n[bar\\\\]\n",
+    "html": "<p><a href=\"/uri\">bar\\</a></p>\n",
+    "example": 530,
+    "start_line": 8149,
+    "end_line": 8155,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[]\n\n[]: /uri\n",
+    "html": "<p>[]</p>\n<p>[]: /uri</p>\n",
+    "example": 531,
+    "start_line": 8160,
+    "end_line": 8167,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[\n ]\n\n[\n ]: /uri\n",
+    "html": "<p>[\n]</p>\n<p>[\n]: /uri</p>\n",
+    "example": 532,
+    "start_line": 8170,
+    "end_line": 8181,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 533,
+    "start_line": 8193,
+    "end_line": 8199,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n",
+    "example": 534,
+    "start_line": 8202,
+    "end_line": 8208,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n",
+    "example": 535,
+    "start_line": 8213,
+    "end_line": 8219,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo] \n[]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a>\n[]</p>\n",
+    "example": 536,
+    "start_line": 8226,
+    "end_line": 8234,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 537,
+    "start_line": 8246,
+    "end_line": 8252,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[*foo* bar]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n",
+    "example": 538,
+    "start_line": 8255,
+    "end_line": 8261,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[[*foo* bar]]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p>[<a href=\"/url\" title=\"title\"><em>foo</em> bar</a>]</p>\n",
+    "example": 539,
+    "start_line": 8264,
+    "end_line": 8270,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[[bar [foo]\n\n[foo]: /url\n",
+    "html": "<p>[[bar <a href=\"/url\">foo</a></p>\n",
+    "example": 540,
+    "start_line": 8273,
+    "end_line": 8279,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n",
+    "example": 541,
+    "start_line": 8284,
+    "end_line": 8290,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo] bar\n\n[foo]: /url\n",
+    "html": "<p><a href=\"/url\">foo</a> bar</p>\n",
+    "example": 542,
+    "start_line": 8295,
+    "end_line": 8301,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "\\[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>[foo]</p>\n",
+    "example": 543,
+    "start_line": 8307,
+    "end_line": 8313,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo*]: /url\n\n*[foo*]\n",
+    "html": "<p>*<a href=\"/url\">foo*</a></p>\n",
+    "example": 544,
+    "start_line": 8319,
+    "end_line": 8325,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar]\n\n[foo]: /url1\n[bar]: /url2\n",
+    "html": "<p><a href=\"/url2\">foo</a></p>\n",
+    "example": 545,
+    "start_line": 8331,
+    "end_line": 8338,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][]\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"/url1\">foo</a></p>\n",
+    "example": 546,
+    "start_line": 8340,
+    "end_line": 8346,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]()\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"\">foo</a></p>\n",
+    "example": 547,
+    "start_line": 8350,
+    "end_line": 8356,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo](not a link)\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"/url1\">foo</a>(not a link)</p>\n",
+    "example": 548,
+    "start_line": 8358,
+    "end_line": 8364,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url\n",
+    "html": "<p>[foo]<a href=\"/url\">bar</a></p>\n",
+    "example": 549,
+    "start_line": 8369,
+    "end_line": 8375,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[bar]: /url2\n",
+    "html": "<p><a href=\"/url2\">foo</a><a href=\"/url1\">baz</a></p>\n",
+    "example": 550,
+    "start_line": 8381,
+    "end_line": 8388,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[foo]: /url2\n",
+    "html": "<p>[foo]<a href=\"/url1\">bar</a></p>\n",
+    "example": 551,
+    "start_line": 8394,
+    "end_line": 8401,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo](/url \"title\")\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 552,
+    "start_line": 8417,
+    "end_line": 8421,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo *bar*]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 553,
+    "start_line": 8424,
+    "end_line": 8430,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo ![bar](/url)](/url2)\n",
+    "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n",
+    "example": 554,
+    "start_line": 8433,
+    "end_line": 8437,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo [bar](/url)](/url2)\n",
+    "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n",
+    "example": 555,
+    "start_line": 8440,
+    "end_line": 8444,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo *bar*][]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 556,
+    "start_line": 8454,
+    "end_line": 8460,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo *bar*][foobar]\n\n[FOOBAR]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 557,
+    "start_line": 8463,
+    "end_line": 8469,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo](train.jpg)\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo\" /></p>\n",
+    "example": 558,
+    "start_line": 8472,
+    "end_line": 8476,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "My ![foo bar](/path/to/train.jpg  \"title\"   )\n",
+    "html": "<p>My <img src=\"/path/to/train.jpg\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 559,
+    "start_line": 8479,
+    "end_line": 8483,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo](<url>)\n",
+    "html": "<p><img src=\"url\" alt=\"foo\" /></p>\n",
+    "example": 560,
+    "start_line": 8486,
+    "end_line": 8490,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![](/url)\n",
+    "html": "<p><img src=\"/url\" alt=\"\" /></p>\n",
+    "example": 561,
+    "start_line": 8493,
+    "end_line": 8497,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo][bar]\n\n[bar]: /url\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n",
+    "example": 562,
+    "start_line": 8502,
+    "end_line": 8508,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo][bar]\n\n[BAR]: /url\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n",
+    "example": 563,
+    "start_line": 8511,
+    "end_line": 8517,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 564,
+    "start_line": 8522,
+    "end_line": 8528,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 565,
+    "start_line": 8531,
+    "end_line": 8537,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![Foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n",
+    "example": 566,
+    "start_line": 8542,
+    "end_line": 8548,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo] \n[]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" />\n[]</p>\n",
+    "example": 567,
+    "start_line": 8554,
+    "end_line": 8562,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 568,
+    "start_line": 8567,
+    "end_line": 8573,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![*foo* bar]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 569,
+    "start_line": 8576,
+    "end_line": 8582,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![[foo]]\n\n[[foo]]: /url \"title\"\n",
+    "html": "<p>![[foo]]</p>\n<p>[[foo]]: /url &quot;title&quot;</p>\n",
+    "example": 570,
+    "start_line": 8587,
+    "end_line": 8594,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![Foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n",
+    "example": 571,
+    "start_line": 8599,
+    "end_line": 8605,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "\\!\\[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>![foo]</p>\n",
+    "example": 572,
+    "start_line": 8611,
+    "end_line": 8617,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "\\![foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>!<a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 573,
+    "start_line": 8623,
+    "end_line": 8629,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar.baz>\n",
+    "html": "<p><a href=\"http://foo.bar.baz\">http://foo.bar.baz</a></p>\n",
+    "example": 574,
+    "start_line": 8656,
+    "end_line": 8660,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar.baz/test?q=hello&id=22&boolean>\n",
+    "html": "<p><a href=\"http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean\">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>\n",
+    "example": 575,
+    "start_line": 8663,
+    "end_line": 8667,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<irc://foo.bar:2233/baz>\n",
+    "html": "<p><a href=\"irc://foo.bar:2233/baz\">irc://foo.bar:2233/baz</a></p>\n",
+    "example": 576,
+    "start_line": 8670,
+    "end_line": 8674,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<MAILTO:FOO@BAR.BAZ>\n",
+    "html": "<p><a href=\"MAILTO:FOO@BAR.BAZ\">MAILTO:FOO@BAR.BAZ</a></p>\n",
+    "example": 577,
+    "start_line": 8679,
+    "end_line": 8683,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a+b+c:d>\n",
+    "html": "<p><a href=\"a+b+c:d\">a+b+c:d</a></p>\n",
+    "example": 578,
+    "start_line": 8691,
+    "end_line": 8695,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<made-up-scheme://foo,bar>\n",
+    "html": "<p><a href=\"made-up-scheme://foo,bar\">made-up-scheme://foo,bar</a></p>\n",
+    "example": 579,
+    "start_line": 8698,
+    "end_line": 8702,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://../>\n",
+    "html": "<p><a href=\"http://../\">http://../</a></p>\n",
+    "example": 580,
+    "start_line": 8705,
+    "end_line": 8709,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<localhost:5001/foo>\n",
+    "html": "<p><a href=\"localhost:5001/foo\">localhost:5001/foo</a></p>\n",
+    "example": 581,
+    "start_line": 8712,
+    "end_line": 8716,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar/baz bim>\n",
+    "html": "<p>&lt;http://foo.bar/baz bim&gt;</p>\n",
+    "example": 582,
+    "start_line": 8721,
+    "end_line": 8725,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://example.com/\\[\\>\n",
+    "html": "<p><a href=\"http://example.com/%5C%5B%5C\">http://example.com/\\[\\</a></p>\n",
+    "example": 583,
+    "start_line": 8730,
+    "end_line": 8734,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo@bar.example.com>\n",
+    "html": "<p><a href=\"mailto:foo@bar.example.com\">foo@bar.example.com</a></p>\n",
+    "example": 584,
+    "start_line": 8752,
+    "end_line": 8756,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo+special@Bar.baz-bar0.com>\n",
+    "html": "<p><a href=\"mailto:foo+special@Bar.baz-bar0.com\">foo+special@Bar.baz-bar0.com</a></p>\n",
+    "example": 585,
+    "start_line": 8759,
+    "end_line": 8763,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo\\+@bar.example.com>\n",
+    "html": "<p>&lt;foo+@bar.example.com&gt;</p>\n",
+    "example": 586,
+    "start_line": 8768,
+    "end_line": 8772,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<>\n",
+    "html": "<p>&lt;&gt;</p>\n",
+    "example": 587,
+    "start_line": 8777,
+    "end_line": 8781,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "< http://foo.bar >\n",
+    "html": "<p>&lt; http://foo.bar &gt;</p>\n",
+    "example": 588,
+    "start_line": 8784,
+    "end_line": 8788,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<m:abc>\n",
+    "html": "<p>&lt;m:abc&gt;</p>\n",
+    "example": 589,
+    "start_line": 8791,
+    "end_line": 8795,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo.bar.baz>\n",
+    "html": "<p>&lt;foo.bar.baz&gt;</p>\n",
+    "example": 590,
+    "start_line": 8798,
+    "end_line": 8802,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "http://example.com\n",
+    "html": "<p>http://example.com</p>\n",
+    "example": 591,
+    "start_line": 8805,
+    "end_line": 8809,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo@bar.example.com\n",
+    "html": "<p>foo@bar.example.com</p>\n",
+    "example": 592,
+    "start_line": 8812,
+    "end_line": 8816,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "www.commonmark.org\n",
+    "html": "<p><a href=\"http://www.commonmark.org\">www.commonmark.org</a></p>\n",
+    "example": 593,
+    "start_line": 8838,
+    "end_line": 8842,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "Visit www.commonmark.org/help for more information.\n",
+    "html": "<p>Visit <a href=\"http://www.commonmark.org/help\">www.commonmark.org/help</a> for more information.</p>\n",
+    "example": 594,
+    "start_line": 8846,
+    "end_line": 8850,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "Visit www.commonmark.org.\n\nVisit www.commonmark.org/a.b.\n",
+    "html": "<p>Visit <a href=\"http://www.commonmark.org\">www.commonmark.org</a>.</p>\n<p>Visit <a href=\"http://www.commonmark.org/a.b\">www.commonmark.org/a.b</a>.</p>\n",
+    "example": 595,
+    "start_line": 8858,
+    "end_line": 8865,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.google.com/search?q=Markup+(business)\n\n(www.google.com/search?q=Markup+(business))\n",
+    "html": "<p><a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a></p>\n<p>(<a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a>)</p>\n",
+    "example": 596,
+    "start_line": 8872,
+    "end_line": 8879,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.google.com/search?q=(business))+ok\n",
+    "html": "<p><a href=\"http://www.google.com/search?q=(business))+ok\">www.google.com/search?q=(business))+ok</a></p>\n",
+    "example": 597,
+    "start_line": 8885,
+    "end_line": 8889,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.google.com/search?q=commonmark&hl=en\n\nwww.google.com/search?q=commonmark&hl;\n",
+    "html": "<p><a href=\"http://www.google.com/search?q=commonmark&amp;hl=en\">www.google.com/search?q=commonmark&amp;hl=en</a></p>\n<p><a href=\"http://www.google.com/search?q=commonmark\">www.google.com/search?q=commonmark</a>&amp;hl;</p>\n",
+    "example": 598,
+    "start_line": 8896,
+    "end_line": 8903,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.commonmark.org/he<lp\n",
+    "html": "<p><a href=\"http://www.commonmark.org/he\">www.commonmark.org/he</a>&lt;lp</p>\n",
+    "example": 599,
+    "start_line": 8907,
+    "end_line": 8911,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "http://commonmark.org\n\n(Visit https://encrypted.google.com/search?q=Markup+(business))\n\nAnonymous FTP is available at ftp://foo.bar.baz.\n",
+    "html": "<p><a href=\"http://commonmark.org\">http://commonmark.org</a></p>\n<p>(Visit <a href=\"https://encrypted.google.com/search?q=Markup+(business)\">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>\n<p>Anonymous FTP is available at <a href=\"ftp://foo.bar.baz\">ftp://foo.bar.baz</a>.</p>\n",
+    "example": 600,
+    "start_line": 8918,
+    "end_line": 8928,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "foo@bar.baz\n",
+    "html": "<p><a href=\"mailto:foo@bar.baz\">foo@bar.baz</a></p>\n",
+    "example": 601,
+    "start_line": 8944,
+    "end_line": 8948,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.\n",
+    "html": "<p>hello@mail+xyz.example isn't valid, but <a href=\"mailto:hello+xyz@mail.example\">hello+xyz@mail.example</a> is.</p>\n",
+    "example": 602,
+    "start_line": 8952,
+    "end_line": 8956,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "a.b-c_d@a.b\n\na.b-c_d@a.b.\n\na.b-c_d@a.b-\n\na.b-c_d@a.b_\n",
+    "html": "<p><a href=\"mailto:a.b-c_d@a.b\">a.b-c_d@a.b</a></p>\n<p><a href=\"mailto:a.b-c_d@a.b\">a.b-c_d@a.b</a>.</p>\n<p>a.b-c_d@a.b-</p>\n<p>a.b-c_d@a.b_</p>\n",
+    "example": 603,
+    "start_line": 8962,
+    "end_line": 8975,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "<a><bab><c2c>\n",
+    "html": "<p><a><bab><c2c></p>\n",
+    "example": 604,
+    "start_line": 9054,
+    "end_line": 9058,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a/><b2/>\n",
+    "html": "<p><a/><b2/></p>\n",
+    "example": 605,
+    "start_line": 9063,
+    "end_line": 9067,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a  /><b2\ndata=\"foo\" >\n",
+    "html": "<p><a  /><b2\ndata=\"foo\" ></p>\n",
+    "example": 606,
+    "start_line": 9072,
+    "end_line": 9078,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 />\n",
+    "html": "<p><a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 /></p>\n",
+    "example": 607,
+    "start_line": 9083,
+    "end_line": 9089,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo <responsive-image src=\"foo.jpg\" />\n",
+    "html": "<p>Foo <responsive-image src=\"foo.jpg\" /></p>\n",
+    "example": 608,
+    "start_line": 9094,
+    "end_line": 9098,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<33> <__>\n",
+    "html": "<p>&lt;33&gt; &lt;__&gt;</p>\n",
+    "example": 609,
+    "start_line": 9103,
+    "end_line": 9107,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a h*#ref=\"hi\">\n",
+    "html": "<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>\n",
+    "example": 610,
+    "start_line": 9112,
+    "end_line": 9116,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"hi'> <a href=hi'>\n",
+    "html": "<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>\n",
+    "example": 611,
+    "start_line": 9121,
+    "end_line": 9125,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "< a><\nfoo><bar/ >\n",
+    "html": "<p>&lt; a&gt;&lt;\nfoo&gt;&lt;bar/ &gt;</p>\n",
+    "example": 612,
+    "start_line": 9130,
+    "end_line": 9136,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href='bar'title=title>\n",
+    "html": "<p>&lt;a href='bar'title=title&gt;</p>\n",
+    "example": 613,
+    "start_line": 9141,
+    "end_line": 9145,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "</a></foo >\n",
+    "html": "<p></a></foo ></p>\n",
+    "example": 614,
+    "start_line": 9150,
+    "end_line": 9154,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "</a href=\"foo\">\n",
+    "html": "<p>&lt;/a href=&quot;foo&quot;&gt;</p>\n",
+    "example": 615,
+    "start_line": 9159,
+    "end_line": 9163,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <!-- this is a\ncomment - with hyphen -->\n",
+    "html": "<p>foo <!-- this is a\ncomment - with hyphen --></p>\n",
+    "example": 616,
+    "start_line": 9168,
+    "end_line": 9174,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <!-- not a comment -- two hyphens -->\n",
+    "html": "<p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>\n",
+    "example": 617,
+    "start_line": 9177,
+    "end_line": 9181,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <!--> foo -->\n\nfoo <!-- foo--->\n",
+    "html": "<p>foo &lt;!--&gt; foo --&gt;</p>\n<p>foo &lt;!-- foo---&gt;</p>\n",
+    "example": 618,
+    "start_line": 9186,
+    "end_line": 9193,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <?php echo $a; ?>\n",
+    "html": "<p>foo <?php echo $a; ?></p>\n",
+    "example": 619,
+    "start_line": 9198,
+    "end_line": 9202,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <!ELEMENT br EMPTY>\n",
+    "html": "<p>foo <!ELEMENT br EMPTY></p>\n",
+    "example": 620,
+    "start_line": 9207,
+    "end_line": 9211,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <![CDATA[>&<]]>\n",
+    "html": "<p>foo <![CDATA[>&<]]></p>\n",
+    "example": 621,
+    "start_line": 9216,
+    "end_line": 9220,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <a href=\"&ouml;\">\n",
+    "html": "<p>foo <a href=\"&ouml;\"></p>\n",
+    "example": 622,
+    "start_line": 9226,
+    "end_line": 9230,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <a href=\"\\*\">\n",
+    "html": "<p>foo <a href=\"\\*\"></p>\n",
+    "example": 623,
+    "start_line": 9235,
+    "end_line": 9239,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"\\\"\">\n",
+    "html": "<p>&lt;a href=&quot;&quot;&quot;&gt;</p>\n",
+    "example": 624,
+    "start_line": 9242,
+    "end_line": 9246,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<strong> <title> <style> <em>\n\n<blockquote>\n  <xmp> is disallowed.\n</blockquote>\n",
+    "html": "<p><strong> &lt;title> &lt;style> <em></p>\n<blockquote>\n  &lt;xmp> is disallowed.\n</blockquote>\n",
+    "example": 625,
+    "start_line": 9273,
+    "end_line": 9284,
+    "section": "Disallowed Raw HTML (extension)",
+    "extensions": [
+      "tagfilter"
+    ]
+  },
+  {
+    "markdown": "foo  \nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 626,
+    "start_line": 9295,
+    "end_line": 9301,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 627,
+    "start_line": 9307,
+    "end_line": 9313,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo       \nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 628,
+    "start_line": 9318,
+    "end_line": 9324,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo  \n     bar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 629,
+    "start_line": 9329,
+    "end_line": 9335,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\n     bar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 630,
+    "start_line": 9338,
+    "end_line": 9344,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo  \nbar*\n",
+    "html": "<p><em>foo<br />\nbar</em></p>\n",
+    "example": 631,
+    "start_line": 9350,
+    "end_line": 9356,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo\\\nbar*\n",
+    "html": "<p><em>foo<br />\nbar</em></p>\n",
+    "example": 632,
+    "start_line": 9359,
+    "end_line": 9365,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "`code  \nspan`\n",
+    "html": "<p><code>code span</code></p>\n",
+    "example": 633,
+    "start_line": 9370,
+    "end_line": 9375,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "`code\\\nspan`\n",
+    "html": "<p><code>code\\ span</code></p>\n",
+    "example": 634,
+    "start_line": 9378,
+    "end_line": 9383,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"foo  \nbar\">\n",
+    "html": "<p><a href=\"foo  \nbar\"></p>\n",
+    "example": 635,
+    "start_line": 9388,
+    "end_line": 9394,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"foo\\\nbar\">\n",
+    "html": "<p><a href=\"foo\\\nbar\"></p>\n",
+    "example": 636,
+    "start_line": 9397,
+    "end_line": 9403,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\n",
+    "html": "<p>foo\\</p>\n",
+    "example": 637,
+    "start_line": 9410,
+    "end_line": 9414,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo  \n",
+    "html": "<p>foo</p>\n",
+    "example": 638,
+    "start_line": 9417,
+    "end_line": 9421,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo\\\n",
+    "html": "<h3>foo\\</h3>\n",
+    "example": 639,
+    "start_line": 9424,
+    "end_line": 9428,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo  \n",
+    "html": "<h3>foo</h3>\n",
+    "example": 640,
+    "start_line": 9431,
+    "end_line": 9435,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\nbaz\n",
+    "html": "<p>foo\nbaz</p>\n",
+    "example": 641,
+    "start_line": 9446,
+    "end_line": 9452,
+    "section": "Soft line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo \n baz\n",
+    "html": "<p>foo\nbaz</p>\n",
+    "example": 642,
+    "start_line": 9458,
+    "end_line": 9464,
+    "section": "Soft line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "hello $.;'there\n",
+    "html": "<p>hello $.;'there</p>\n",
+    "example": 643,
+    "start_line": 9478,
+    "end_line": 9482,
+    "section": "Textual content",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo \u03c7\u03c1\u1fc6\u03bd\n",
+    "html": "<p>Foo \u03c7\u03c1\u1fc6\u03bd</p>\n",
+    "example": 644,
+    "start_line": 9485,
+    "end_line": 9489,
+    "section": "Textual content",
+    "extensions": []
+  },
+  {
+    "markdown": "Multiple     spaces\n",
+    "html": "<p>Multiple     spaces</p>\n",
+    "example": 645,
+    "start_line": 9494,
+    "end_line": 9498,
+    "section": "Textual content",
+    "extensions": []
+  }
+]
\ No newline at end of file
diff --git a/pub/markdown/tool/common_mark_stats.dart b/pub/markdown/tool/stats.dart
similarity index 87%
rename from pub/markdown/tool/common_mark_stats.dart
rename to pub/markdown/tool/stats.dart
index d76003c..e6a785a 100644
--- a/pub/markdown/tool/common_mark_stats.dart
+++ b/pub/markdown/tool/stats.dart
@@ -8,11 +8,9 @@
 import 'package:collection/collection.dart';
 import 'package:html/dom.dart';
 import 'package:html/parser.dart' show parseFragment;
-import 'package:markdown/markdown.dart' show markdownToHtml;
+import 'package:markdown/markdown.dart' show markdownToHtml, ExtensionSet;
 import 'package:path/path.dart' as p;
 
-const _commonMarkTests = 'common_mark_tests.json';
-
 // Locate the "tool" directory. Use mirrors so that this works with the test
 // package, which loads this suite into an isolate.
 String get _currentDir => p
@@ -30,6 +28,8 @@
         negatable: false)
     ..addFlag('verbose',
         defaultsTo: false, help: 'verbose output', negatable: false)
+    ..addOption('flavor',
+        allowed: ['common_mark', 'gfm'], defaultsTo: 'common_mark')
     ..addFlag('help', defaultsTo: false, negatable: false);
 
   ArgResults options;
@@ -60,7 +60,14 @@
     return;
   }
 
-  var sections = _loadCommonMarkSections();
+  final testPrefix = options['flavor'];
+
+  ExtensionSet extensionSet;
+  if (testPrefix == 'gfm') {
+    extensionSet = ExtensionSet.gitHub;
+  }
+
+  var sections = _loadCommonMarkSections(testPrefix);
 
   var scores = new SplayTreeMap<String, SplayTreeMap<int, CompareLevel>>(
       compareAsciiLowerCaseNatural);
@@ -73,23 +80,25 @@
       var nestedMap = scores.putIfAbsent(
           section, () => new SplayTreeMap<int, CompareLevel>());
 
-      nestedMap[e.example] = _compareResult(e, verbose);
+      nestedMap[e.example] =
+          _compareResult(e, verbose, extensionSet: extensionSet);
     }
   });
 
   if (raw || updateFiles) {
-    await _printRaw(scores, updateFiles);
+    await _printRaw(testPrefix, scores, updateFiles);
   }
 
   if (!raw || updateFiles) {
-    await _printFriendly(scores, updateFiles);
+    await _printFriendly(testPrefix, scores, updateFiles);
   }
 }
 
-CompareLevel _compareResult(CommonMarkTestCase expected, bool verboseFail) {
+CompareLevel _compareResult(CommonMarkTestCase expected, bool verboseFail,
+    {ExtensionSet extensionSet}) {
   String output;
   try {
-    output = markdownToHtml(expected.markdown);
+    output = markdownToHtml(expected.markdown, extensionSet: extensionSet);
   } catch (err, stackTrace) {
     if (verboseFail) {
       printVerboseFailure(
@@ -144,7 +153,7 @@
       case CompareLevel.loose:
         return 'loose';
       default:
-        throw 'huh?';
+        throw new ArgumentError("`$obj` is unknown.");
     }
   }
   if (obj is Map) {
@@ -158,10 +167,10 @@
   return obj;
 }
 
-Future _printRaw(Map scores, bool updateFiles) async {
+Future _printRaw(String testPrefix, Map scores, bool updateFiles) async {
   IOSink sink;
   if (updateFiles) {
-    var path = p.join(_currentDir, 'common_mark_stats.json');
+    var path = p.join(_currentDir, '${testPrefix}_stats.json');
     print('Updating $path');
     var file = new File(path);
     sink = file.openWrite();
@@ -183,6 +192,7 @@
 }
 
 Future _printFriendly(
+    String testPrefix,
     SplayTreeMap<String, SplayTreeMap<int, CompareLevel>> scores,
     bool updateFiles) async {
   const countWidth = 4;
@@ -192,7 +202,7 @@
 
   IOSink sink;
   if (updateFiles) {
-    var path = p.join(_currentDir, 'common_mark_stats.txt');
+    var path = p.join(_currentDir, '${testPrefix}_stats.txt');
     print('Updating $path');
     var file = new File(path);
     sink = file.openWrite();
@@ -284,8 +294,9 @@
   return true;
 }
 
-Map<String, List<CommonMarkTestCase>> _loadCommonMarkSections() {
-  var testFile = new File(p.join(_currentDir, _commonMarkTests));
+Map<String, List<CommonMarkTestCase>> _loadCommonMarkSections(
+    String testPrefix) {
+  var testFile = new File(p.join(_currentDir, '${testPrefix}_tests.json'));
   var testsJson = testFile.readAsStringSync();
 
   var testArray = JSON.decode(testsJson) as List<Map<String, dynamic>>;
diff --git a/pub/matcher/BUILD.gn b/pub/matcher/BUILD.gn
index 6f85b98..4e1d96e 100644
--- a/pub/matcher/BUILD.gn
+++ b/pub/matcher/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for matcher-0.12.0+2
+# This file is generated by importer.py for matcher-0.12.1+1
 
 import("//build/dart/dart_package.gni")
 
@@ -10,5 +10,6 @@
   disable_analysis = true
 
   deps = [
+    "//third_party/dart-pkg/pub/stack_trace",
   ]
 }
diff --git a/pub/matcher/CHANGELOG.md b/pub/matcher/CHANGELOG.md
index ed15206..f36f40d 100644
--- a/pub/matcher/CHANGELOG.md
+++ b/pub/matcher/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.12.1+1
+
+* Produce a better error message when a `CustomMatcher`'s feature throws.
+
+## 0.12.1
+
+* Add containsAllInOrder matcher for Iterables
+
 ## 0.12.0+2
 
 * Fix all strong-mode warnings.
diff --git a/pub/matcher/lib/matcher.dart b/pub/matcher/lib/matcher.dart
index f4ebf08..b4b9d22 100644
--- a/pub/matcher/lib/matcher.dart
+++ b/pub/matcher/lib/matcher.dart
@@ -11,5 +11,6 @@
 export 'src/map_matchers.dart';
 export 'src/numeric_matchers.dart';
 export 'src/operator_matchers.dart';
+export 'src/order_matchers.dart';
 export 'src/string_matchers.dart';
 export 'src/util.dart';
diff --git a/pub/matcher/lib/src/core_matchers.dart b/pub/matcher/lib/src/core_matchers.dart
index a313d31..94f9d7d 100644
--- a/pub/matcher/lib/src/core_matchers.dart
+++ b/pub/matcher/lib/src/core_matchers.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:stack_trace/stack_trace.dart';
+
 import 'description.dart';
 import 'interfaces.dart';
 import 'util.dart';
@@ -121,7 +123,7 @@
 
     var expectedIterator = expected.iterator;
     var actualIterator = actual.iterator;
-    for (var index = 0; ; index++) {
+    for (var index = 0;; index++) {
       // Advance in lockstep.
       var expectedNext = expectedIterator.moveNext();
       var actualNext = actualIterator.moveNext();
@@ -261,7 +263,7 @@
 
   Description describeMismatch(
       item, Description mismatchDescription, Map matchState, bool verbose) {
-    var reason = matchState['reason'];
+    var reason = matchState['reason'] ?? '';
     // If we didn't get a good reason, that would normally be a
     // simple 'is <value>' message. We only add that if the mismatch
     // description is non empty (so we are supplementing the mismatch
@@ -308,11 +310,11 @@
       }
       if (start == minLength) {
         if (escapedValue.length < escapedItem.length) {
-          buff.write(' Both strings start the same, but the given value also'
+          buff.write(' Both strings start the same, but the actual value also'
               ' has the following trailing characters: ');
           _writeTrailing(buff, escapedItem, escapedValue.length);
         } else {
-          buff.write(' Both strings start the same, but the given value is'
+          buff.write(' Both strings start the same, but the actual value is'
               ' missing the following trailing characters: ');
           _writeTrailing(buff, escapedValue, escapedItem.length);
         }
@@ -361,7 +363,7 @@
 }
 
 /// Returns a matcher that matches if an object is an instance
-/// of [type] (or a subtype).
+/// of [T] (or a subtype).
 ///
 /// As types are not first class objects in Dart we can only
 /// approximate this test by using a generic wrapper class.
@@ -528,8 +530,8 @@
   Description describeMismatch(
       item, Description mismatchDescription, Map matchState, bool verbose) {
     if (item is String || item is Iterable || item is Map) {
-      return super.describeMismatch(
-          item, mismatchDescription, matchState, verbose);
+      return super
+          .describeMismatch(item, mismatchDescription, matchState, verbose);
     } else {
       return mismatchDescription.add('is not a string, map or iterable');
     }
@@ -614,9 +616,23 @@
   featureValueOf(actual) => actual;
 
   bool matches(item, Map matchState) {
-    var f = featureValueOf(item);
-    if (_matcher.matches(f, matchState)) return true;
-    addStateInfo(matchState, {'feature': f});
+    try {
+      var f = featureValueOf(item);
+      if (_matcher.matches(f, matchState)) return true;
+      addStateInfo(matchState, {'custom.feature': f});
+    } catch (exception, stack) {
+      addStateInfo(matchState, {
+        'custom.exception': exception.toString(),
+        'custom.stack': new Chain.forTrace(stack)
+            .foldFrames(
+                (frame) =>
+                    frame.package == 'test' ||
+                    frame.package == 'stream_channel' ||
+                    frame.package == 'matcher',
+                terse: true)
+            .toString()
+      });
+    }
     return false;
   }
 
@@ -625,14 +641,25 @@
 
   Description describeMismatch(
       item, Description mismatchDescription, Map matchState, bool verbose) {
+    if (matchState['custom.exception'] != null) {
+      mismatchDescription
+          .add('threw ')
+          .addDescriptionOf(matchState['custom.exception'])
+          .add('\n')
+          .add(matchState['custom.stack'].toString());
+      return mismatchDescription;
+    }
+
     mismatchDescription
         .add('has ')
         .add(_featureName)
         .add(' with value ')
-        .addDescriptionOf(matchState['feature']);
+        .addDescriptionOf(matchState['custom.feature']);
     var innerDescription = new StringDescription();
-    _matcher.describeMismatch(
-        matchState['feature'], innerDescription, matchState['state'], verbose);
+
+    _matcher.describeMismatch(matchState['custom.feature'], innerDescription,
+        matchState['state'], verbose);
+
     if (innerDescription.length > 0) {
       mismatchDescription.add(' which ').add(innerDescription.toString());
     }
diff --git a/pub/matcher/lib/src/interfaces.dart b/pub/matcher/lib/src/interfaces.dart
index 0183671..1c8091e 100644
--- a/pub/matcher/lib/src/interfaces.dart
+++ b/pub/matcher/lib/src/interfaces.dart
@@ -52,7 +52,7 @@
   /// A few matchers make use of the [verbose] flag to provide detailed
   /// information that is not typically included but can be of help in
   /// diagnosing failures, such as stack traces.
-  Description describeMismatch(
-      item, Description mismatchDescription, Map matchState, bool verbose) =>
+  Description describeMismatch(item, Description mismatchDescription,
+          Map matchState, bool verbose) =>
       mismatchDescription;
 }
diff --git a/pub/matcher/lib/src/iterable_matchers.dart b/pub/matcher/lib/src/iterable_matchers.dart
index 55724b7..9159104 100644
--- a/pub/matcher/lib/src/iterable_matchers.dart
+++ b/pub/matcher/lib/src/iterable_matchers.dart
@@ -55,8 +55,8 @@
       mismatchDescription.add(' at index $index');
       return mismatchDescription;
     }
-    return super.describeMismatch(
-        item, mismatchDescription, matchState, verbose);
+    return super
+        .describeMismatch(item, mismatchDescription, matchState, verbose);
   }
 }
 
@@ -136,8 +136,8 @@
     if (item is! Iterable) {
       return mismatchDescription.addDescriptionOf(item).add(' not an Iterable');
     } else {
-      return super.describeMismatch(
-          item, mismatchDescription, matchState, verbose);
+      return super
+          .describeMismatch(item, mismatchDescription, matchState, verbose);
     }
   }
 }
@@ -200,8 +200,8 @@
       .addAll('[', ', ', ']', _expected)
       .add(' unordered');
 
-  Description describeMismatch(
-      item, Description mismatchDescription, Map matchState, bool verbose) =>
+  Description describeMismatch(item, Description mismatchDescription,
+          Map matchState, bool verbose) =>
       mismatchDescription.add(_test(item));
 }
 
@@ -211,8 +211,8 @@
 /// returning whether they match, will be applied to each pair in order.
 /// [description] should be a meaningful name for the comparator.
 Matcher pairwiseCompare(
-    Iterable expected, bool comparator(a, b), String description) =>
-        new _PairwiseCompare(expected, comparator, description);
+        Iterable expected, bool comparator(a, b), String description) =>
+    new _PairwiseCompare(expected, comparator, description);
 
 typedef bool _Comparator(a, b);
 
@@ -231,11 +231,8 @@
     for (var e in _expected) {
       iterator.moveNext();
       if (!_comparator(e, iterator.current)) {
-        addStateInfo(matchState, {
-          'index': i,
-          'expected': e,
-          'actual': iterator.current
-        });
+        addStateInfo(matchState,
+            {'index': i, 'expected': e, 'actual': iterator.current});
         return false;
       }
       i++;
@@ -263,3 +260,47 @@
     }
   }
 }
+
+/// Matches [Iterable]s which contain an element matching every value in
+/// [expected] in the same order, but may contain additional values interleaved
+/// throughout.
+///
+/// For example: `[0, 1, 0, 2, 0]` matches `containsAllInOrder([1, 2])` but not
+/// `containsAllInOrder([2, 1])` or `containsAllInOrder([1, 2, 3])`.
+Matcher containsAllInOrder(Iterable expected) =>
+    new _ContainsAllInOrder(expected);
+
+class _ContainsAllInOrder implements Matcher {
+  final Iterable _expected;
+
+  _ContainsAllInOrder(this._expected);
+
+  String _test(item, Map matchState) {
+    if (item is! Iterable) return 'not an iterable';
+    var matchers = _expected.map(wrapMatcher).toList();
+    var matcherIndex = 0;
+    for (var value in item) {
+      if (matchers[matcherIndex].matches(value, matchState)) matcherIndex++;
+      if (matcherIndex == matchers.length) return null;
+    }
+    return new StringDescription()
+        .add('did not find a value matching ')
+        .addDescriptionOf(matchers[matcherIndex])
+        .add(' following expected prior values')
+        .toString();
+  }
+
+  @override
+  bool matches(item, Map matchState) => _test(item, matchState) == null;
+
+  @override
+  Description describe(Description description) => description
+      .add('contains in order(')
+      .addDescriptionOf(_expected)
+      .add(')');
+
+  @override
+  Description describeMismatch(item, Description mismatchDescription,
+          Map matchState, bool verbose) =>
+      mismatchDescription.add(_test(item, matchState));
+}
diff --git a/pub/matcher/lib/src/numeric_matchers.dart b/pub/matcher/lib/src/numeric_matchers.dart
index 0cdb98c..e8651de 100644
--- a/pub/matcher/lib/src/numeric_matchers.dart
+++ b/pub/matcher/lib/src/numeric_matchers.dart
@@ -4,103 +4,6 @@
 
 import 'interfaces.dart';
 
-/// Returns a matcher which matches if the match argument is greater
-/// than the given [value].
-Matcher greaterThan(value) =>
-    new _OrderingComparison(value, false, false, true, 'a value greater than');
-
-/// Returns a matcher which matches if the match argument is greater
-/// than or equal to the given [value].
-Matcher greaterThanOrEqualTo(value) => new _OrderingComparison(
-    value, true, false, true, 'a value greater than or equal to');
-
-/// Returns a matcher which matches if the match argument is less
-/// than the given [value].
-Matcher lessThan(value) =>
-    new _OrderingComparison(value, false, true, false, 'a value less than');
-
-/// Returns a matcher which matches if the match argument is less
-/// than or equal to the given [value].
-Matcher lessThanOrEqualTo(value) => new _OrderingComparison(
-    value, true, true, false, 'a value less than or equal to');
-
-/// A matcher which matches if the match argument is zero.
-const Matcher isZero =
-    const _OrderingComparison(0, true, false, false, 'a value equal to');
-
-/// A matcher which matches if the match argument is non-zero.
-const Matcher isNonZero =
-    const _OrderingComparison(0, false, true, true, 'a value not equal to');
-
-/// A matcher which matches if the match argument is positive.
-const Matcher isPositive =
-    const _OrderingComparison(0, false, false, true, 'a positive value', false);
-
-/// A matcher which matches if the match argument is zero or negative.
-const Matcher isNonPositive = const _OrderingComparison(
-    0, true, true, false, 'a non-positive value', false);
-
-/// A matcher which matches if the match argument is negative.
-const Matcher isNegative =
-    const _OrderingComparison(0, false, true, false, 'a negative value', false);
-
-/// A matcher which matches if the match argument is zero or positive.
-const Matcher isNonNegative = const _OrderingComparison(
-    0, true, false, true, 'a non-negative value', false);
-
-bool _isNumeric(value) {
-  return value is num;
-}
-
-// TODO(kevmoo) Note that matchers that use _OrderingComparison only use
-// `==` and `<` operators to evaluate the match. Or change the matcher.
-class _OrderingComparison extends Matcher {
-  /// Expected value.
-  final _value;
-  /// What to return if actual == expected
-  final bool _equalValue;
-  /// What to return if actual < expected
-  final bool _lessThanValue;
-  /// What to return if actual > expected
-  final bool _greaterThanValue;
-  /// Textual name of the inequality
-  final String _comparisonDescription;
-  /// Whether to include the expected value in the description
-  final bool _valueInDescription;
-
-  const _OrderingComparison(this._value, this._equalValue, this._lessThanValue,
-      this._greaterThanValue, this._comparisonDescription,
-      [bool valueInDescription = true])
-      : this._valueInDescription = valueInDescription;
-
-  bool matches(item, Map matchState) {
-    if (item == _value) {
-      return _equalValue;
-    } else if (item < _value) {
-      return _lessThanValue;
-    } else {
-      return _greaterThanValue;
-    }
-  }
-
-  Description describe(Description description) {
-    if (_valueInDescription) {
-      return description
-          .add(_comparisonDescription)
-          .add(' ')
-          .addDescriptionOf(_value);
-    } else {
-      return description.add(_comparisonDescription);
-    }
-  }
-
-  Description describeMismatch(
-      item, Description mismatchDescription, Map matchState, bool verbose) {
-    mismatchDescription.add('is not ');
-    return describe(mismatchDescription);
-  }
-}
-
 /// Returns a matcher which matches if the match argument is within [delta]
 /// of some [value].
 ///
@@ -114,9 +17,8 @@
   const _IsCloseTo(this._value, this._delta);
 
   bool matches(item, Map matchState) {
-    if (!_isNumeric(item)) {
-      return false;
-    }
+    if (item is! num) return false;
+
     var diff = item - _value;
     if (diff < 0) diff = -diff;
     return (diff <= _delta);
@@ -183,18 +85,18 @@
     return true;
   }
 
-  Description describe(Description description) => description.add(
-      "be in range from "
-      "$_low (${_lowMatchValue ? 'inclusive' : 'exclusive'}) to "
-      "$_high (${_highMatchValue ? 'inclusive' : 'exclusive'})");
+  Description describe(Description description) =>
+      description.add("be in range from "
+          "$_low (${_lowMatchValue ? 'inclusive' : 'exclusive'}) to "
+          "$_high (${_highMatchValue ? 'inclusive' : 'exclusive'})");
 
   Description describeMismatch(
       item, Description mismatchDescription, Map matchState, bool verbose) {
     if (item is! num) {
       return mismatchDescription.addDescriptionOf(item).add(' not numeric');
     } else {
-      return super.describeMismatch(
-          item, mismatchDescription, matchState, verbose);
+      return super
+          .describeMismatch(item, mismatchDescription, matchState, verbose);
     }
   }
 }
diff --git a/pub/matcher/lib/src/order_matchers.dart b/pub/matcher/lib/src/order_matchers.dart
new file mode 100644
index 0000000..b6079e9
--- /dev/null
+++ b/pub/matcher/lib/src/order_matchers.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'interfaces.dart';
+
+/// Returns a matcher which matches if the match argument is greater
+/// than the given [value].
+Matcher greaterThan(value) =>
+    new _OrderingMatcher(value, false, false, true, 'a value greater than');
+
+/// Returns a matcher which matches if the match argument is greater
+/// than or equal to the given [value].
+Matcher greaterThanOrEqualTo(value) => new _OrderingMatcher(
+    value, true, false, true, 'a value greater than or equal to');
+
+/// Returns a matcher which matches if the match argument is less
+/// than the given [value].
+Matcher lessThan(value) =>
+    new _OrderingMatcher(value, false, true, false, 'a value less than');
+
+/// Returns a matcher which matches if the match argument is less
+/// than or equal to the given [value].
+Matcher lessThanOrEqualTo(value) => new _OrderingMatcher(
+    value, true, true, false, 'a value less than or equal to');
+
+/// A matcher which matches if the match argument is zero.
+const Matcher isZero =
+    const _OrderingMatcher(0, true, false, false, 'a value equal to');
+
+/// A matcher which matches if the match argument is non-zero.
+const Matcher isNonZero =
+    const _OrderingMatcher(0, false, true, true, 'a value not equal to');
+
+/// A matcher which matches if the match argument is positive.
+const Matcher isPositive =
+    const _OrderingMatcher(0, false, false, true, 'a positive value', false);
+
+/// A matcher which matches if the match argument is zero or negative.
+const Matcher isNonPositive =
+    const _OrderingMatcher(0, true, true, false, 'a non-positive value', false);
+
+/// A matcher which matches if the match argument is negative.
+const Matcher isNegative =
+    const _OrderingMatcher(0, false, true, false, 'a negative value', false);
+
+/// A matcher which matches if the match argument is zero or positive.
+const Matcher isNonNegative =
+    const _OrderingMatcher(0, true, false, true, 'a non-negative value', false);
+
+// TODO(kevmoo) Note that matchers that use _OrderingComparison only use
+// `==` and `<` operators to evaluate the match. Or change the matcher.
+class _OrderingMatcher extends Matcher {
+  /// Expected value.
+  final _value;
+
+  /// What to return if actual == expected
+  final bool _equalValue;
+
+  /// What to return if actual < expected
+  final bool _lessThanValue;
+
+  /// What to return if actual > expected
+  final bool _greaterThanValue;
+
+  /// Textual name of the inequality
+  final String _comparisonDescription;
+
+  /// Whether to include the expected value in the description
+  final bool _valueInDescription;
+
+  const _OrderingMatcher(this._value, this._equalValue, this._lessThanValue,
+      this._greaterThanValue, this._comparisonDescription,
+      [bool valueInDescription = true])
+      : this._valueInDescription = valueInDescription;
+
+  bool matches(item, Map matchState) {
+    if (item == _value) {
+      return _equalValue;
+    } else if (item < _value) {
+      return _lessThanValue;
+    } else {
+      return _greaterThanValue;
+    }
+  }
+
+  Description describe(Description description) {
+    if (_valueInDescription) {
+      return description
+          .add(_comparisonDescription)
+          .add(' ')
+          .addDescriptionOf(_value);
+    } else {
+      return description.add(_comparisonDescription);
+    }
+  }
+
+  Description describeMismatch(
+      item, Description mismatchDescription, Map matchState, bool verbose) {
+    mismatchDescription.add('is not ');
+    return describe(mismatchDescription);
+  }
+}
diff --git a/pub/matcher/lib/src/pretty_print.dart b/pub/matcher/lib/src/pretty_print.dart
index 9b0a789..826cad0 100644
--- a/pub/matcher/lib/src/pretty_print.dart
+++ b/pub/matcher/lib/src/pretty_print.dart
@@ -49,9 +49,13 @@
       }
 
       // Otherwise, print each member on its own line.
-      return "$type[\n" + strings.map((string) {
-        return _indent(indent + 2) + string;
-      }).join(",\n") + "\n" + _indent(indent) + "]";
+      return "$type[\n" +
+          strings.map((string) {
+            return _indent(indent + 2) + string;
+          }).join(",\n") +
+          "\n" +
+          _indent(indent) +
+          "]";
     } else if (object is Map) {
       // Convert the contents of the map to string representations.
       var strings = object.keys.map((key) {
@@ -73,9 +77,13 @@
       }
 
       // Otherwise, print each key/value pair on its own line.
-      return "{\n" + strings.map((string) {
-        return _indent(indent + 2) + string;
-      }).join(",\n") + "\n" + _indent(indent) + "}";
+      return "{\n" +
+          strings.map((string) {
+            return _indent(indent + 2) + string;
+          }).join(",\n") +
+          "\n" +
+          _indent(indent) +
+          "}";
     } else if (object is String) {
       // Escape strings and print each line on its own line.
       var lines = object.split("\n");
diff --git a/pub/matcher/lib/src/string_matchers.dart b/pub/matcher/lib/src/string_matchers.dart
index eb0b464..d8bbdb8 100644
--- a/pub/matcher/lib/src/string_matchers.dart
+++ b/pub/matcher/lib/src/string_matchers.dart
@@ -65,8 +65,8 @@
           .addDescriptionOf(collapseWhitespace(item))
           .add(' with whitespace compressed');
     } else {
-      return super.describeMismatch(
-          item, mismatchDescription, matchState, verbose);
+      return super
+          .describeMismatch(item, mismatchDescription, matchState, verbose);
     }
   }
 }
@@ -169,8 +169,8 @@
     if (!(item is String)) {
       return mismatchDescription.addDescriptionOf(item).add(' not a string');
     } else {
-      return super.describeMismatch(
-          item, mismatchDescription, matchState, verbose);
+      return super
+          .describeMismatch(item, mismatchDescription, matchState, verbose);
     }
   }
 }
diff --git a/pub/matcher/pubspec.yaml b/pub/matcher/pubspec.yaml
index 3697fe6..a274b9d 100644
--- a/pub/matcher/pubspec.yaml
+++ b/pub/matcher/pubspec.yaml
@@ -1,9 +1,12 @@
 name: matcher
-version: 0.12.0+2
+
+version: 0.12.1+1
 author: Dart Team <misc@dartlang.org>
 description: Support for specifying test expectations
 homepage: https://github.com/dart-lang/matcher
 environment:
-  sdk: '>=1.0.0 <2.0.0'
+  sdk: '>=1.8.0 <2.0.0'
+dependencies:
+  stack_trace: '^1.2.0'
 dev_dependencies:
   test: '>=0.12.0 <0.13.0'
diff --git a/pub/path/BUILD.gn b/pub/path/BUILD.gn
index 8ce7b85..8f4a3be 100644
--- a/pub/path/BUILD.gn
+++ b/pub/path/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for path-1.4.1
+# This file is generated by importer.py for path-1.4.2
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/path/CHANGELOG.md b/pub/path/CHANGELOG.md
index f7dde67..b29d2ab 100644
--- a/pub/path/CHANGELOG.md
+++ b/pub/path/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.4.2
+
+* Treat `package:` URLs as absolute.
+
+* Normalize `c:\foo\.` to `c:\foo`.
+
 ## 1.4.1
 
 * Root-relative URLs like `/foo` are now resolved relative to the drive letter
diff --git a/pub/path/lib/src/context.dart b/pub/path/lib/src/context.dart
index c5ebb69..a00ca29 100644
--- a/pub/path/lib/src/context.dart
+++ b/pub/path/lib/src/context.dart
@@ -397,7 +397,7 @@
     // Single dots and double dots are normalized to directory traversals.
     if (previous == chars.PERIOD &&
         (previousPrevious == null ||
-         previousPrevious == chars.SLASH ||
+         style.isSeparator(previousPrevious) ||
          previousPrevious == chars.PERIOD)) {
       return true;
     }
diff --git a/pub/path/lib/src/style/url.dart b/pub/path/lib/src/style/url.dart
index f4bab64..2e29aa7 100644
--- a/pub/path/lib/src/style/url.dart
+++ b/pub/path/lib/src/style/url.dart
@@ -41,19 +41,29 @@
     if (path.isEmpty) return 0;
     if (isSeparator(path.codeUnitAt(0))) return 1;
 
+    for (var i = 0; i < path.length; i++) {
+      var codeUnit = path.codeUnitAt(i);
+      if (isSeparator(codeUnit)) return 0;
+      if (codeUnit == chars.COLON) {
+        if (i == 0) return 0;
+
+        // The root part is up until the next '/', or the full path. Skip ':'
+        // (and '//' if it exists) and search for '/' after that.
+        if (path.startsWith('//', i + 1)) i += 3;
+        var index = path.indexOf('/', i);
+        if (index <= 0) return path.length;
+
+        // file: URLs sometimes consider Windows drive letters part of the root.
+        // See https://url.spec.whatwg.org/#file-slash-state.
+        if (!withDrive || path.length < index + 3) return index;
+        if (!path.startsWith('file://')) return index;
+        if (!isDriveLetter(path, index + 1)) return index;
+        return path.length == index + 3 ? index + 3 : index + 4;
+      }
+    }
+
     var index = path.indexOf("/");
     if (index > 0 && path.startsWith('://', index - 1)) {
-      // The root part is up until the next '/', or the full path. Skip
-      // '://' and search for '/' after that.
-      index = path.indexOf('/', index + 2);
-      if (index <= 0) return path.length;
-
-      // file: URLs sometimes consider Windows drive letters part of the root.
-      // See https://url.spec.whatwg.org/#file-slash-state.
-      if (!withDrive || path.length < index + 3) return index;
-      if (!path.startsWith('file://')) return index;
-      if (!isDriveLetter(path, index + 1)) return index;
-      return path.length == index + 3 ? index + 3 : index + 4;
     }
     return 0;
   }
diff --git a/pub/path/pubspec.yaml b/pub/path/pubspec.yaml
index 48e799b..2c90e1c 100644
--- a/pub/path/pubspec.yaml
+++ b/pub/path/pubspec.yaml
@@ -1,5 +1,5 @@
 name: path
-version: 1.4.1
+version: 1.4.2
 author: Dart Team <misc@dartlang.org>
 description: >
  A string-based path manipulation library. All of the path operations you know
diff --git a/pub/petitparser/.travis.yml b/pub/petitparser/.travis.yml
index 6acd367..bf94adb 100644
--- a/pub/petitparser/.travis.yml
+++ b/pub/petitparser/.travis.yml
@@ -9,6 +9,5 @@
 cache:
   directories:
     - $HOME/.pub-cache
-with_content_shell: true
 script:
   - ./tool/travis.sh
diff --git a/pub/petitparser/BUILD.gn b/pub/petitparser/BUILD.gn
index f066a84..51ba567 100644
--- a/pub/petitparser/BUILD.gn
+++ b/pub/petitparser/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for petitparser-1.5.4
+# This file is generated by importer.py for petitparser-1.5.5
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/petitparser/LICENSE b/pub/petitparser/LICENSE
index 5527e52..83e5792 100644
--- a/pub/petitparser/LICENSE
+++ b/pub/petitparser/LICENSE
@@ -1,6 +1,6 @@
 The MIT License
 
-Copyright (c) 2006-2016 Lukas Renggli.
+Copyright (c) 2006-2017 Lukas Renggli.
 All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/pub/petitparser/.analysis_options b/pub/petitparser/analysis_options.yaml
similarity index 100%
rename from pub/petitparser/.analysis_options
rename to pub/petitparser/analysis_options.yaml
diff --git a/pub/petitparser/example/lispshell/lispshell.dart b/pub/petitparser/example/lispshell/lispshell.dart
index e9636f6..19a0181 100644
--- a/pub/petitparser/example/lispshell/lispshell.dart
+++ b/pub/petitparser/example/lispshell/lispshell.dart
@@ -62,8 +62,12 @@
   var environment = Natives.import(new Environment());
 
   // add additional primitives
-  environment.define(new Name('exit'), (env, args) => exit(args == null ? 0 : args.head));
-  environment.define(new Name('sleep'), (env, args) => sleep(new Duration(milliseconds: args.head)));
+  environment.define(new Name('exit'), (Environment env, Cons args) {
+    exit(args == null ? 0 : args.head);
+  });
+  environment.define(new Name('sleep'), (Environment env, Cons args) {
+    sleep(new Duration(milliseconds: args.head));
+  });
 
   // process standard library
   if (standardLibrary) {
diff --git a/pub/petitparser/example/lispweb/lispweb.dart b/pub/petitparser/example/lispweb/lispweb.dart
index 32e25ab..f15ad77 100644
--- a/pub/petitparser/example/lispweb/lispweb.dart
+++ b/pub/petitparser/example/lispweb/lispweb.dart
@@ -27,7 +27,7 @@
   var output = querySelector('#output') as TextAreaElement;
 
   querySelector('#evaluate').onClick.listen((event) {
-    var result = evalString(lispParser, environment, input.value);
+    Object result = evalString(lispParser, environment, input.value);
     output.value = result.toString();
     inspector(querySelector('#inspector'), environment);
   });
diff --git a/pub/petitparser/lib/lisp.dart b/pub/petitparser/lib/lisp.dart
index 6f23996..b5b697f 100644
--- a/pub/petitparser/lib/lisp.dart
+++ b/pub/petitparser/lib/lisp.dart
@@ -30,7 +30,7 @@
 }
 
 /// Evaluate a cons of instructions.
-evalList(Environment env, expr) {
+evalList(Environment env, Cons expr) {
   var result = null;
   while (expr is Cons) {
     result = eval(env, expr.head);
diff --git a/pub/petitparser/lib/src/debug/profile.dart b/pub/petitparser/lib/src/debug/profile.dart
index b4e4424..d03fbc6 100644
--- a/pub/petitparser/lib/src/debug/profile.dart
+++ b/pub/petitparser/lib/src/debug/profile.dart
@@ -19,9 +19,9 @@
 /// the second number is the microseconds spent in this parser and all its
 /// children.
 Parser profile(Parser root, [OutputHandler output = print]) {
-  var count = new Map();
-  var watch = new Map();
-  var parsers = new List();
+  Map<Parser, int> count = new Map();
+  Map<Parser, Stopwatch> watch = new Map();
+  List<Parser> parsers = new List();
   return new ContinuationParser(transformParser(root, (parser) {
     parsers.add(parser);
     return new ContinuationParser(parser, (continuation, context) {
diff --git a/pub/petitparser/lib/src/json/grammar.dart b/pub/petitparser/lib/src/json/grammar.dart
index ba76150..82f0a03 100644
--- a/pub/petitparser/lib/src/json/grammar.dart
+++ b/pub/petitparser/lib/src/json/grammar.dart
@@ -10,7 +10,7 @@
   const JsonGrammarDefinition();
 
   start() => ref(value).end();
-  token(p) => p.flatten().trim();
+  token(Parser p) => p.flatten().trim();
 
   array() => ref(token, char('['))
       & ref(elements).optional()
diff --git a/pub/petitparser/lib/src/lisp/cons.dart b/pub/petitparser/lib/src/lisp/cons.dart
index e9fcae7..a4602f8 100644
--- a/pub/petitparser/lib/src/lisp/cons.dart
+++ b/pub/petitparser/lib/src/lisp/cons.dart
@@ -3,22 +3,36 @@
 /// The basic data structure of LISP.
 class Cons {
 
-  /// The head of the cons.
-  dynamic head;
+  /// The first object.
+  Object car;
 
-  /// The tail of the cons.
-  dynamic tail;
+  /// The head of the cons.
+  Object get head => this.car;
+
+  /// The second object.
+  Object cdr;
+
+  /// The tail of the cons, if applicable.
+  Cons get tail {
+    if (cdr is Cons) {
+      return cdr as Cons;
+    } else if (cdr == null) {
+      return null;
+    } else {
+      throw new StateError('${toString()} does not have a tail.');
+    }
+  }
 
   /// Constructs a cons.
-  Cons(this.head, this.tail);
+  Cons(this.car, [this.cdr]);
 
   @override
   bool operator ==(other) {
-    return other is Cons && head == other.head && tail == other.tail;
+    return other is Cons && car == other.car && cdr == other.cdr;
   }
 
   @override
-  int get hashCode => 31 * head.hashCode + tail.hashCode;
+  int get hashCode => 31 * car.hashCode + cdr.hashCode;
 
   @override
   String toString() {
@@ -26,8 +40,8 @@
     buffer.write('(');
     var current = this;
     while (current is Cons) {
-      buffer.write(current.head.toString());
-      current = current.tail;
+      buffer.write(current.car.toString());
+      current = current.cdr;
       if (current != null) {
         buffer.write(' ');
       }
diff --git a/pub/petitparser/lib/src/lisp/natives.dart b/pub/petitparser/lib/src/lisp/natives.dart
index 0b8551e..8e4e6a2 100644
--- a/pub/petitparser/lib/src/lisp/natives.dart
+++ b/pub/petitparser/lib/src/lisp/natives.dart
@@ -48,22 +48,24 @@
     return environment;
   }
 
-  static _define(Environment env, args) {
+  static _define(Environment env, Cons args) {
     if (args.head is Name) {
       return env.define(args.head, evalList(env, args.tail));
-    } else if (args.head.head is Name) {
-      return env.define(
-          args.head.head, _lambda(env, new Cons(args.head.tail, args.tail)));
+    } else if (args.head is Cons) {
+      Cons head = args.head;
+      if (head.head is Name) {
+        return env.define(head.head, _lambda(env, new Cons(head.tail, args.tail)));
+      }
     } else {
       throw new ArgumentError('Invalid define: $args');
     }
   }
 
-  static _lambda(Environment lambdaEnv, lambdaArgs) {
-    return (Environment evalEnv, evalArgs) {
-      var inner = lambdaEnv.create();
-      var names = lambdaArgs.head;
-      var values = evalArguments(evalEnv, evalArgs);
+  static _lambda(Environment lambdaEnv, Cons lambdaArgs) {
+    return (Environment evalEnv, Cons evalArgs) {
+      Environment inner = lambdaEnv.create();
+      Cons names = lambdaArgs.head;
+      Cons values = evalArguments(evalEnv, evalArgs);
       while (names != null && values != null) {
         inner.define(names.head, values.head);
         names = names.tail;
@@ -73,33 +75,34 @@
     };
   }
 
-  static _quote(Environment env, args) {
+  static _quote(Environment env, Cons args) {
     return args;
   }
 
-  static _eval(Environment env, args) {
+  static _eval(Environment env, Cons args) {
     return eval(env.create(), eval(env, args.head));
   }
 
-  static _apply(Environment env, args) {
+  static _apply(Environment env, Cons args) {
     return eval(env, args.head)(env.create(), args.tail);
   }
 
-  static _let(Environment env, args) {
-    var inner = env.create();
-    var binding = args.head;
-    while (binding != null) {
-      inner.define(binding.head.head, eval(env, binding.head.tail.head));
+  static _let(Environment env, Cons args) {
+    Environment inner = env.create();
+    Cons binding = args.head;
+    while (binding is Cons) {
+      Cons definition = binding.head;
+      inner.define(definition.head, eval(env, definition.tail.head));
       binding = binding.tail;
     }
     return evalList(inner, args.tail);
   }
 
-  static _set(Environment env, args) {
+  static _set(Environment env, Cons args) {
     return env[args.head] = eval(env, args.tail.head);
   }
 
-  static _print(Environment env, args) {
+  static _print(Environment env, Cons args) {
     var buffer = new StringBuffer();
     while (args != null) {
       buffer.write(eval(env, args.head));
@@ -109,7 +112,7 @@
     return null;
   }
 
-  static _if(Environment env, args) {
+  static _if(Environment env, Cons args) {
     var condition = eval(env, args.head);
     if (condition) {
       if (args.tail != null) {
@@ -123,7 +126,7 @@
     return null;
   }
 
-  static _while(Environment env, args) {
+  static _while(Environment env, Cons args) {
     var result = null;
     while (eval(env, args.head)) {
       result = evalList(env, args.tail);
@@ -131,7 +134,7 @@
     return result;
   }
 
-  static _and(Environment env, args) {
+  static _and(Environment env, Cons args) {
     while (args != null) {
       if (!eval(env, args.head)) {
         return false;
@@ -141,7 +144,7 @@
     return true;
   }
 
-  static _or(Environment env, args) {
+  static _or(Environment env, Cons args) {
     while (args != null) {
       if (eval(env, args.head)) {
         return true;
@@ -151,11 +154,11 @@
     return false;
   }
 
-  static _not(Environment env, args) {
+  static _not(Environment env, Cons args) {
     return !eval(env, args.head);
   }
 
-  static _plus(Environment env, args) {
+  static _plus(Environment env, Cons args) {
     var value = eval(env, args.head);
     for (args = args.tail; args != null; args = args.tail) {
       value += eval(env, args.head);
@@ -163,7 +166,7 @@
     return value;
   }
 
-  static _minus(Environment env, args) {
+  static _minus(Environment env, Cons args) {
     var value = eval(env, args.head);
     if (args.tail == null) {
       return -value;
@@ -174,7 +177,7 @@
     return value;
   }
 
-  static _multiply(Environment env, args) {
+  static _multiply(Environment env, Cons args) {
     var value = eval(env, args.head);
     for (args = args.tail; args != null; args = args.tail) {
       value *= eval(env, args.head);
@@ -182,7 +185,7 @@
     return value;
   }
 
-  static _divide(Environment env, args) {
+  static _divide(Environment env, Cons args) {
     var value = eval(env, args.head);
     for (args = args.tail; args != null; args = args.tail) {
       value /= eval(env, args.head);
@@ -190,7 +193,7 @@
     return value;
   }
 
-  static _modulo(Environment env, args) {
+  static _modulo(Environment env, Cons args) {
     var value = eval(env, args.head);
     for (args = args.tail; args != null; args = args.tail) {
       value %= eval(env, args.head);
@@ -198,56 +201,56 @@
     return value;
   }
 
-  static _smaller(Environment env, args) {
+  static _smaller(Environment env, Cons args) {
     return eval(env, args.head) < eval(env, args.tail.head);
   }
 
-  static _smallerOrEqual(Environment env, args) {
+  static _smallerOrEqual(Environment env, Cons args) {
     return eval(env, args.head) <= eval(env, args.tail.head);
   }
 
-  static _equal(Environment env, args) {
+  static _equal(Environment env, Cons args) {
     return eval(env, args.head) == eval(env, args.tail.head);
   }
 
-  static _notEqual(Environment env, args) {
+  static _notEqual(Environment env, Cons args) {
     return eval(env, args.head) != eval(env, args.tail.head);
   }
 
-  static _larger(Environment env, args) {
+  static _larger(Environment env, Cons args) {
     return eval(env, args.head) > eval(env, args.tail.head);
   }
 
-  static _largerOrEqual(Environment env, args) {
+  static _largerOrEqual(Environment env, Cons args) {
     return eval(env, args.head) >= eval(env, args.tail.head);
   }
 
-  static _cons(Environment env, args) {
-    return new Cons(eval(env, args.head), eval(env, args.tail.head));
+  static _cons(Environment env, Cons args) {
+    return new Cons(eval(env, args.head),  eval(env, args.tail.head));
   }
 
-  static _car(Environment env, args) {
+  static _car(Environment env, Cons args) {
     var cons = eval(env, args.head);
     return cons is Cons ? cons.head : null;
   }
 
-  static _carSet(Environment env, args) {
+  static _carSet(Environment env, Cons args) {
     var cons = eval(env, args.head);
     if (cons is Cons) {
-      cons.head = eval(env, args.tail.head);
+      cons.car = eval(env, args.tail.head);
     }
     return cons;
   }
 
-  static _cdr(Environment env, args) {
+  static _cdr(Environment env, Cons args) {
     var cons = eval(env, args.head);
-    return cons is Cons ? cons.tail : null;
+    return cons is Cons ? cons.cdr : null;
   }
 
-  static _cdrSet(Environment env, args) {
+  static _cdrSet(Environment env, Cons args) {
     var cons = eval(env, args.head);
     if (cons is Cons) {
-      cons.tail = eval(env, args.tail.head);
+      cons.cdr = eval(env, args.tail.head);
     }
     return cons;
   }
diff --git a/pub/petitparser/lib/src/petitparser/actions.dart b/pub/petitparser/lib/src/petitparser/actions.dart
index 482eb06..2deddb6 100644
--- a/pub/petitparser/lib/src/petitparser/actions.dart
+++ b/pub/petitparser/lib/src/petitparser/actions.dart
@@ -101,8 +101,7 @@
   Result parseOn(Context context) {
     var result = _delegate.parseOn(context);
     if (result.isSuccess) {
-      var token = new Token(
-          result.value, context.buffer, context.position, result.position);
+      var token = new Token(result.value, context.buffer, context.position, result.position);
       return result.success(token);
     } else {
       return result;
diff --git a/pub/petitparser/lib/src/petitparser/characters.dart b/pub/petitparser/lib/src/petitparser/characters.dart
index 6a9dbc2..eb31ff0 100644
--- a/pub/petitparser/lib/src/petitparser/characters.dart
+++ b/pub/petitparser/lib/src/petitparser/characters.dart
@@ -65,7 +65,7 @@
 CharacterPredicate _optimizedRanges(Iterable<_RangeCharPredicate> ranges) {
 
   // 1. sort the ranges
-  var sortedRanges = new List.from(ranges, growable: false);
+  List<_RangeCharPredicate> sortedRanges = new List.from(ranges, growable: false);
   sortedRanges.sort((first, second) {
     return first.start != second.start
         ? first.start - second.start
@@ -73,7 +73,7 @@
   });
 
   // 2. merge adjacent or overlapping ranges
-  var mergedRanges = new List();
+  List<_RangeCharPredicate> mergedRanges = new List();
   for (var thisRange in sortedRanges) {
     if (mergedRanges.isEmpty) {
       mergedRanges.add(thisRange);
@@ -95,8 +95,8 @@
         : mergedRanges[0];
   } else {
     return new _RangesCharPredicate(mergedRanges.length,
-        mergedRanges.map((range) => range.start).toList(growable: false) as List<int>,
-        mergedRanges.map((range) => range.stop).toList(growable: false) as List<int>);
+        mergedRanges.map((range) => range.start).toList(growable: false),
+        mergedRanges.map((range) => range.stop).toList(growable: false));
   }
 }
 
@@ -147,8 +147,7 @@
   const _LetterCharPredicate();
 
   @override
-  bool test(int value) =>
-      (65 <= value && value <= 90) || (97 <= value && value <= 122);
+  bool test(int value) => (65 <= value && value <= 90) || (97 <= value && value <= 122);
 }
 
 const _letterCharPredicate = const _LetterCharPredicate();
@@ -311,7 +310,7 @@
 const _wordCharPredicate = const _WordCharPredicate();
 
 // internal converter for character codes
-int _toCharCode(element) {
+int _toCharCode(Object element) {
   if (element is num) {
     return element.round();
   }
diff --git a/pub/petitparser/lib/src/petitparser/combinators.dart b/pub/petitparser/lib/src/petitparser/combinators.dart
index 36a4336..fda3c0e 100644
--- a/pub/petitparser/lib/src/petitparser/combinators.dart
+++ b/pub/petitparser/lib/src/petitparser/combinators.dart
@@ -162,7 +162,7 @@
 
   @override
   Result parseOn(Context context) {
-    var result;
+    Result result;
     for (var i = 0; i < _parsers.length; i++) {
       result = _parsers[i].parseOn(context);
       if (result.isSuccess) {
diff --git a/pub/petitparser/lib/src/petitparser/composite.dart b/pub/petitparser/lib/src/petitparser/composite.dart
index a74f3cf..2565d2f 100644
--- a/pub/petitparser/lib/src/petitparser/composite.dart
+++ b/pub/petitparser/lib/src/petitparser/composite.dart
@@ -119,8 +119,7 @@
     } else if (!_defined.containsKey(name)) {
       throw new UndefinedProductionError(name);
     } else {
-      _defined[name] =
-          replacement is Parser ? replacement : replacement(_defined[name]);
+      _defined[name] = replacement is Parser ? replacement : replacement(_defined[name]);
     }
   }
 
@@ -133,7 +132,7 @@
   ///
   ///     action('list', (list) => list.length);
   void action(String name, Function function) {
-    redef(name, (parser) => parser.map(function));
+    redef(name, (Parser parser) => parser.map(function));
   }
 }
 
diff --git a/pub/petitparser/lib/src/petitparser/definition.dart b/pub/petitparser/lib/src/petitparser/definition.dart
index 44b7d72..be30fe9 100644
--- a/pub/petitparser/lib/src/petitparser/definition.dart
+++ b/pub/petitparser/lib/src/petitparser/definition.dart
@@ -69,7 +69,7 @@
 
   /// Internal helper to resolve a complete parser graph.
   Parser _resolve(_Reference reference) {
-    var mapping = new Map();
+    Map<_Reference, Parser> mapping = new Map();
 
     Parser _dereference(_Reference reference) {
       var parser = mapping[reference];
@@ -77,14 +77,15 @@
         var references = [reference];
         parser = reference.resolve();
         while (parser is _Reference) {
-          if (references.contains(parser)) {
+          var otherReference = parser as _Reference;
+          if (references.contains(otherReference)) {
             throw new StateError('Recursive references detected: $references');
           }
-          references.add(parser);
-          parser = parser.resolve();
+          references.add(otherReference);
+          parser = otherReference.resolve();
         }
-        for (var each in references) {
-          mapping[each] = parser;
+        for (var otherReference in references) {
+          mapping[otherReference] = parser;
         }
       }
       return parser;
@@ -127,27 +128,29 @@
 
   @override
   bool operator ==(other) {
-    if (other is! _Reference ||
-        other.function != function ||
-        other.arguments.length != arguments.length) {
-      return false;
-    }
-    for (var i = 0; i < arguments.length; i++) {
-      var a = arguments[i],
-          b = other.arguments[i];
-      if (a is Parser && a is! _Reference && b is Parser && b is! _Reference) {
-        // for parsers do a deep equality check
-        if (!a.isEqualTo(b)) {
-          return false;
-        }
-      } else {
-        // for everything else just do standard equality
-        if (a != b) {
-          return false;
+    if (other is _Reference) {
+      if (other.function != function ||
+          other.arguments.length != arguments.length) {
+        return false;
+      }
+      for (var i = 0; i < arguments.length; i++) {
+        var a = arguments[i],
+            b = other.arguments[i];
+        if (a is Parser && a is! _Reference && b is Parser && b is! _Reference) {
+          // for parsers do a deep equality check
+          if (!a.isEqualTo(b)) {
+            return false;
+          }
+        } else {
+          // for everything else just do standard equality
+          if (a != b) {
+            return false;
+          }
         }
       }
+      return true;
     }
-    return true;
+    return false;
   }
 
   @override
diff --git a/pub/petitparser/lib/src/petitparser/repeaters.dart b/pub/petitparser/lib/src/petitparser/repeaters.dart
index 0bb144e..0ebea4f 100644
--- a/pub/petitparser/lib/src/petitparser/repeaters.dart
+++ b/pub/petitparser/lib/src/petitparser/repeaters.dart
@@ -103,7 +103,7 @@
       elements.add(result.value);
       current = result;
     }
-    var contexts = new List.from([current]);
+    List<Context> contexts = new List.from([current]);
     while (_max == unbounded || elements.length < _max) {
       var result = _delegate.parseOn(current);
       if (result.isFailure) {
diff --git a/pub/petitparser/lib/src/petitparser/token.dart b/pub/petitparser/lib/src/petitparser/token.dart
index 5fd8dcf..0b4152b 100644
--- a/pub/petitparser/lib/src/petitparser/token.dart
+++ b/pub/petitparser/lib/src/petitparser/token.dart
@@ -59,7 +59,7 @@
   /// Converts the [position] index in a [buffer] to a line and column tuple.
   static List<int> lineAndColumnOf(String buffer, int position) {
     var line = 1, offset = 0;
-    for (var token in newlineParser().token().matchesSkipping(buffer)) {
+    for (Token token in newlineParser().token().matchesSkipping(buffer)) {
       if (position < token.stop) {
         return [line, position - offset + 1];
       }
diff --git a/pub/petitparser/lib/src/reflection/optimize.dart b/pub/petitparser/lib/src/reflection/optimize.dart
index c9dd847..47d1b53 100644
--- a/pub/petitparser/lib/src/reflection/optimize.dart
+++ b/pub/petitparser/lib/src/reflection/optimize.dart
@@ -12,7 +12,7 @@
 
 /// Returns a copy of [parser] with all duplicates parsers collapsed.
 Parser removeDuplicates(Parser parser) {
-  var uniques = new Set();
+  Set<Parser> uniques = new Set();
   return transformParser(parser, (source) {
     var target = uniques.firstWhere((each) {
       return source != each && source.isEqualTo(each);
diff --git a/pub/petitparser/lib/src/reflection/transform.dart b/pub/petitparser/lib/src/reflection/transform.dart
index 8ee449f..1e5648d 100644
--- a/pub/petitparser/lib/src/reflection/transform.dart
+++ b/pub/petitparser/lib/src/reflection/transform.dart
@@ -10,12 +10,12 @@
 /// input grammar; then the resulting grammar is traversed until all references
 /// to old parsers are replaced with the transformed ones.
 Parser transformParser(Parser parser, TransformationHandler handler) {
-  var mapping = new Map.identity();
+  Map<Parser, Parser> mapping = new Map.identity();
   for (var each in allParser(parser)) {
     mapping[each] = handler(each.copy());
   }
-  var seen = new Set.from(mapping.values);
-  var todo = new List.from(mapping.values);
+  Set<Parser> seen = new Set.from(mapping.values);
+  List<Parser> todo = new List.from(mapping.values);
   while (todo.isNotEmpty) {
     var parent = todo.removeLast();
     for (var child in parent.children) {
diff --git a/pub/petitparser/lib/src/smalltalk/grammar.dart b/pub/petitparser/lib/src/smalltalk/grammar.dart
index 24a2824..18d5650 100644
--- a/pub/petitparser/lib/src/smalltalk/grammar.dart
+++ b/pub/petitparser/lib/src/smalltalk/grammar.dart
@@ -12,9 +12,12 @@
   // build special token objects
   token(input) {
     if (input is String) {
-      input = input.length == 1 ? char(input) : string(input);
+      return token(input.length == 1 ? char(input) : string(input));
+    } else if (input is Parser) {
+      return input.token().trim(ref(spacer));
+    } else {
+      throw new ArgumentError('Invalid token parser: $input');
     }
-    return input.token().trim(ref(spacer));
   }
 
   // the original implementation uses a handwritten parser to
diff --git a/pub/petitparser/lib/test.dart b/pub/petitparser/lib/test.dart
index 508b2e0..adee030 100644
--- a/pub/petitparser/lib/test.dart
+++ b/pub/petitparser/lib/test.dart
@@ -65,8 +65,9 @@
         return description;
       case 'matcher':
         description.add(' which parse result ');
+        var result = matchState['result'] as Result;
         var subDescription = new StringDescription();
-        matcher.describeMismatch(matchState['result'].value, subDescription,
+        matcher.describeMismatch(result.value, subDescription,
             matchState['state'], verbose);
         if (subDescription.length > 0) {
           description.add(subDescription.toString());
@@ -76,9 +77,10 @@
         }
         return description;
       case 'position':
+        var result = matchState['result'] as Result;
         description
             .add(' that consumes input to ')
-            .add(matchState['result'].position.toString())
+            .add(result.position.toString())
             .add(' instead of ')
             .add(position.toString());
         return description;
diff --git a/pub/petitparser/pubspec.yaml b/pub/petitparser/pubspec.yaml
index 18208c9..53bf218 100644
--- a/pub/petitparser/pubspec.yaml
+++ b/pub/petitparser/pubspec.yaml
@@ -1,5 +1,5 @@
 name: petitparser
-version: 1.5.4
+version: 1.5.5
 author: Lukas Renggli <renggli@gmail.com>
 description: Dynamic parser combinator framework.
 homepage: https://github.com/renggli/dart-petitparser
diff --git a/pub/petitparser/tool/travis.sh b/pub/petitparser/tool/travis.sh
index ea5b146..18ee593 100755
--- a/pub/petitparser/tool/travis.sh
+++ b/pub/petitparser/tool/travis.sh
@@ -10,7 +10,7 @@
     example/**/*.dart
 
 # Verify that all the tests pass.
-dart --checked test/all_tests.dart
+pub run --checked test -p vm test/all_tests.dart
 
 # Verify the coverage of the tests.
 if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then
diff --git a/pub/shelf/.travis.yml b/pub/shelf/.travis.yml
index 0ceff2e..2c46289 100644
--- a/pub/shelf/.travis.yml
+++ b/pub/shelf/.travis.yml
@@ -1,19 +1,42 @@
 language: dart
 sudo: false
 dart:
-  - stable
   - dev
-  - 1.19.0
-  - 1.18.1
-  - 1.17.1
+  - stable
+  - 1.22.1
+  - 1.21.1
+  - 1.20.1
+  - 1.19.1
 cache:
   directories:
     - $HOME/.pub-cache
-with_content_shell: true
-addons:
-  firefox: "latest"
-before_script:
-  - "export DISPLAY=:99.0"
-  - "sh -e /etc/init.d/xvfb start"
-  - 't=0; until (xdpyinfo -display :99 &> /dev/null || test $t -gt 10); do sleep 1; let t=$t+1; done'
-script: ./tool/travis.sh
+dart_task:
+  - test: --platform vm
+  # No parallelism on Firefox (-j 1)
+  # Causes flakiness – need to investigate
+  - test: --platform firefox -j 1
+  - test: --platform dartium
+    install_dartium: true
+matrix:
+  include:
+    # Only validate formatting using the dev release
+    # Formatted with 1.23.0-dev.10.0 which has (good) changes since 1.22.1
+    - dart: dev
+      dart_task: dartfmt
+    # Only care about being analyzer clean for dev and stable
+    - dart: dev
+      dart_task: dartanalyzer
+    - dart: stable
+      dart_task: dartanalyzer
+  exclude:
+    # Exclude Firefox tests on SDKs before 1.22.0-dev.4 which are lacking fix
+    # https://github.com/dart-lang/sdk/commit/7c3c297a8ad907f12bf12b96a21777421067fd18
+    - dart: 1.21.1
+      dart_task:
+        test: --platform firefox -j 1
+    - dart: 1.20.1
+      dart_task:
+        test: --platform firefox -j 1
+    - dart: 1.19.1
+      dart_task:
+        test: --platform firefox -j 1
diff --git a/pub/shelf/BUILD.gn b/pub/shelf/BUILD.gn
index 61472b0..36f3ed9 100644
--- a/pub/shelf/BUILD.gn
+++ b/pub/shelf/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for shelf-0.6.7+2
+# This file is generated by importer.py for shelf-0.6.8
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/shelf/CHANGELOG.md b/pub/shelf/CHANGELOG.md
index 25101d1..9246811 100644
--- a/pub/shelf/CHANGELOG.md
+++ b/pub/shelf/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.8
+
+* Add a `securityContext` parameter to `self_io.serve()`.
+
 ## 0.6.7+2
 
 * Go back to auto-generating a `Content-Length` header when the length is known
diff --git a/pub/shelf/lib/shelf_io.dart b/pub/shelf/lib/shelf_io.dart
index d66bbe0..9a03532 100644
--- a/pub/shelf/lib/shelf_io.dart
+++ b/pub/shelf/lib/shelf_io.dart
@@ -30,14 +30,19 @@
 /// Starts an [HttpServer] that listens on the specified [address] and
 /// [port] and sends requests to [handler].
 ///
-/// See the documentation for [HttpServer.bind] for more details on [address],
-/// [port], and [backlog].
-Future<HttpServer> serve(Handler handler, address, int port, {int backlog}) {
-  if (backlog == null) backlog = 0;
-  return HttpServer.bind(address, port, backlog: backlog).then((server) {
-    serveRequests(server, handler);
-    return server;
-  });
+/// If a [securityContext] is provided an HTTPS server will be started.
+////
+/// See the documentation for [HttpServer.bind] and [HttpServer.bindSecure]
+/// for more details on [address], [port], and [backlog].
+Future<HttpServer> serve(Handler handler, address, int port,
+    {SecurityContext securityContext, int backlog}) async {
+  backlog ??= 0;
+  HttpServer server = await (securityContext == null
+      ? HttpServer.bind(address, port, backlog: backlog)
+      : HttpServer.bindSecure(address, port, securityContext,
+          backlog: backlog));
+  serveRequests(server, handler);
+  return server;
 }
 
 /// Serve a [Stream] of [HttpRequest]s.
@@ -65,8 +70,8 @@
   try {
     shelfRequest = _fromHttpRequest(request);
   } catch (error, stackTrace) {
-    var response = _logTopLevelError(
-        'Error parsing request.\n$error', stackTrace);
+    var response =
+        _logTopLevelError('Error parsing request.\n$error', stackTrace);
     await _writeResponse(response, request.response);
     return;
   }
@@ -81,18 +86,15 @@
     if (!shelfRequest.canHijack) return;
 
     // If the request wasn't hijacked, we shouldn't be seeing this exception.
-    response = _logError(
-        shelfRequest,
-        "Caught HijackException, but the request wasn't hijacked.",
-        stackTrace);
+    response = _logError(shelfRequest,
+        "Caught HijackException, but the request wasn't hijacked.", stackTrace);
   } catch (error, stackTrace) {
-    response = _logError(
-        shelfRequest, 'Error thrown by handler.\n$error', stackTrace);
+    response =
+        _logError(shelfRequest, 'Error thrown by handler.\n$error', stackTrace);
   }
 
   if (response == null) {
-    await _writeResponse(
-        _logError(shelfRequest, 'null response from handler.'),
+    await _writeResponse(_logError(shelfRequest, 'null response from handler.'),
         request.response);
     return;
   } else if (shelfRequest.canHijack) {
@@ -104,8 +106,7 @@
     ..writeln("Got a response for hijacked request "
         "${shelfRequest.method} ${shelfRequest.requestedUri}:")
     ..writeln(response.statusCode);
-  response.headers
-      .forEach((key, value) => message.writeln("${key}: ${value}"));
+  response.headers.forEach((key, value) => message.writeln("${key}: ${value}"));
   throw new Exception(message.toString().trim());
 }
 
@@ -158,8 +159,8 @@
     // otherwise `dart:io` will try to add another layer of chunking.
     //
     // TODO(nweiz): Do this more cleanly when sdk#27886 is fixed.
-    response = response.change(
-        body: chunkedCoding.decoder.bind(response.read()));
+    response =
+        response.change(body: chunkedCoding.decoder.bind(response.read()));
     httpResponse.headers.set(HttpHeaders.TRANSFER_ENCODING, 'chunked');
   } else if (response.statusCode >= 200 &&
       response.statusCode != 204 &&
@@ -205,7 +206,8 @@
     chain = new Chain.forTrace(stackTrace);
   }
   chain = chain
-      .foldFrames((frame) => frame.isCore || frame.package == 'shelf').terse;
+      .foldFrames((frame) => frame.isCore || frame.package == 'shelf')
+      .terse;
 
   stderr.writeln('ERROR - ${new DateTime.now()}');
   stderr.writeln(message);
diff --git a/pub/shelf/lib/src/cascade.dart b/pub/shelf/lib/src/cascade.dart
index 1f3b167..37e531b 100644
--- a/pub/shelf/lib/src/cascade.dart
+++ b/pub/shelf/lib/src/cascade.dart
@@ -80,8 +80,8 @@
 
 /// Computes the [Cascade._shouldCascade] function based on the user's
 /// parameters.
-_ShouldCascade _computeShouldCascade(Iterable<int> statusCodes,
-    bool shouldCascade(Response response)) {
+_ShouldCascade _computeShouldCascade(
+    Iterable<int> statusCodes, bool shouldCascade(Response response)) {
   if (shouldCascade != null) return shouldCascade;
   if (statusCodes == null) statusCodes = [404, 405];
   statusCodes = statusCodes.toSet();
diff --git a/pub/shelf/lib/src/message.dart b/pub/shelf/lib/src/message.dart
index 1f474fd..0f13e85 100644
--- a/pub/shelf/lib/src/message.dart
+++ b/pub/shelf/lib/src/message.dart
@@ -17,7 +17,8 @@
 /// The default set of headers for a message created with no body and no
 /// explicit headers.
 final _defaultHeaders = new ShelfUnmodifiableMap<String>(
-    {"content-length": "0"}, ignoreKeyCase: true);
+    {"content-length": "0"},
+    ignoreKeyCase: true);
 
 /// Represents logic shared between [Request] and [Response].
 abstract class Message {
@@ -61,16 +62,19 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Message(body, {Encoding encoding, Map<String, String> headers,
+  Message(body,
+      {Encoding encoding,
+      Map<String, String> headers,
       Map<String, Object> context})
       : this._(new Body(body, encoding), headers, context);
 
   Message._(Body body, Map<String, String> headers, Map<String, Object> context)
       : _body = body,
         headers = new ShelfUnmodifiableMap<String>(
-            _adjustHeaders(headers, body), ignoreKeyCase: true),
-        context = new ShelfUnmodifiableMap<Object>(context,
-            ignoreKeyCase: false);
+            _adjustHeaders(headers, body),
+            ignoreKeyCase: true),
+        context =
+            new ShelfUnmodifiableMap<Object>(context, ignoreKeyCase: false);
 
   /// The contents of the content-length field in [headers].
   ///
@@ -81,6 +85,7 @@
     _contentLengthCache = int.parse(headers['content-length']);
     return _contentLengthCache;
   }
+
   int _contentLengthCache;
 
   /// The MIME type of the message.
@@ -118,6 +123,7 @@
     _contentTypeCache = new MediaType.parse(headers['content-type']);
     return _contentTypeCache;
   }
+
   MediaType _contentTypeCache;
 
   /// Returns a [Stream] representing the body.
@@ -140,20 +146,18 @@
 
   /// Creates a new [Message] by copying existing values and applying specified
   /// changes.
-  Message change({Map<String, String> headers, Map<String, Object> context,
-      body});
+  Message change(
+      {Map<String, String> headers, Map<String, Object> context, body});
 }
 
 /// Adds information about [encoding] to [headers].
 ///
 /// Returns a new map without modifying [headers].
-Map<String, String> _adjustHeaders(
-    Map<String, String> headers, Body body) {
+Map<String, String> _adjustHeaders(Map<String, String> headers, Body body) {
   var sameEncoding = _sameEncoding(headers, body);
   if (sameEncoding) {
     if (body.contentLength == null ||
-        getHeader(headers, 'content-length') ==
-            body.contentLength.toString()) {
+        getHeader(headers, 'content-length') == body.contentLength.toString()) {
       return headers ?? const ShelfUnmodifiableMap.empty();
     } else if (body.contentLength == 0 &&
         (headers == null || headers.isEmpty)) {
diff --git a/pub/shelf/lib/src/middleware.dart b/pub/shelf/lib/src/middleware.dart
index 3eac69f..a270b4e 100644
--- a/pub/shelf/lib/src/middleware.dart
+++ b/pub/shelf/lib/src/middleware.dart
@@ -46,7 +46,8 @@
 /// does not receive errors thrown by [requestHandler] or [responseHandler], nor
 /// does it receive [HijackException]s. It can either return a new response or
 /// throw an error.
-Middleware createMiddleware({requestHandler(Request request),
+Middleware createMiddleware(
+    {requestHandler(Request request),
     responseHandler(Response response),
     errorHandler(error, StackTrace stackTrace)}) {
   if (requestHandler == null) requestHandler = (request) => null;
@@ -66,8 +67,8 @@
       return new Future.sync(() => requestHandler(request)).then((response) {
         if (response != null) return response;
 
-        return new Future.sync(() => innerHandler(request)).then(
-            (response) => responseHandler(response), onError: onError);
+        return new Future.sync(() => innerHandler(request))
+            .then((response) => responseHandler(response), onError: onError);
       });
     };
   };
diff --git a/pub/shelf/lib/src/middleware/logger.dart b/pub/shelf/lib/src/middleware/logger.dart
index 98866d5..b127315 100644
--- a/pub/shelf/lib/src/middleware/logger.dart
+++ b/pub/shelf/lib/src/middleware/logger.dart
@@ -21,31 +21,31 @@
 /// If [logger] is not passed, the message is just passed to [print].
 Middleware logRequests({void logger(String msg, bool isError)}) =>
     (innerHandler) {
-  if (logger == null) logger = _defaultLogger;
+      if (logger == null) logger = _defaultLogger;
 
-  return (request) {
-    var startTime = new DateTime.now();
-    var watch = new Stopwatch()..start();
+      return (request) {
+        var startTime = new DateTime.now();
+        var watch = new Stopwatch()..start();
 
-    return new Future.sync(() => innerHandler(request)).then((response) {
-      var msg = _getMessage(startTime, response.statusCode,
-          request.requestedUri, request.method, watch.elapsed);
+        return new Future.sync(() => innerHandler(request)).then((response) {
+          var msg = _getMessage(startTime, response.statusCode,
+              request.requestedUri, request.method, watch.elapsed);
 
-      logger(msg, false);
+          logger(msg, false);
 
-      return response;
-    }, onError: (error, stackTrace) {
-      if (error is HijackException) throw error;
+          return response;
+        }, onError: (error, stackTrace) {
+          if (error is HijackException) throw error;
 
-      var msg = _getErrorMessage(startTime, request.requestedUri,
-          request.method, watch.elapsed, error, stackTrace);
+          var msg = _getErrorMessage(startTime, request.requestedUri,
+              request.method, watch.elapsed, error, stackTrace);
 
-      logger(msg, true);
+          logger(msg, true);
 
-      throw error;
-    });
-  };
-};
+          throw error;
+        });
+      };
+    };
 
 String _formatQuery(String query) {
   return query == '' ? '' : '?$query';
@@ -62,7 +62,8 @@
   var chain = new Chain.current();
   if (stack != null) {
     chain = new Chain.forTrace(stack)
-        .foldFrames((frame) => frame.isCore || frame.package == 'shelf').terse;
+        .foldFrames((frame) => frame.isCore || frame.package == 'shelf')
+        .terse;
   }
 
   var msg = '${requestTime}\t$elapsedTime\t$method\t${requestedUri.path}'
diff --git a/pub/shelf/lib/src/request.dart b/pub/shelf/lib/src/request.dart
index 0d0154d..b297879 100644
--- a/pub/shelf/lib/src/request.dart
+++ b/pub/shelf/lib/src/request.dart
@@ -85,6 +85,7 @@
     _ifModifiedSinceCache = parseHttpDate(headers['if-modified-since']);
     return _ifModifiedSinceCache;
   }
+
   DateTime _ifModifiedSinceCache;
 
   /// Creates a new [Request].
@@ -133,20 +134,25 @@
   ///
   /// See also [hijack].
   // TODO(kevmoo) finish documenting the rest of the arguments.
-  Request(String method, Uri requestedUri, {String protocolVersion,
-      Map<String, String> headers, String handlerPath, Uri url, body,
-      Encoding encoding, Map<String, Object> context,
-      void onHijack(void hijack(
-          Stream<List<int>> stream, StreamSink<List<int>> sink))})
+  Request(String method, Uri requestedUri,
+      {String protocolVersion,
+      Map<String, String> headers,
+      String handlerPath,
+      Uri url,
+      body,
+      Encoding encoding,
+      Map<String, Object> context,
+      void onHijack(
+          void hijack(Stream<List<int>> stream, StreamSink<List<int>> sink))})
       : this._(method, requestedUri,
-          protocolVersion: protocolVersion,
-          headers: headers,
-          url: url,
-          handlerPath: handlerPath,
-          body: body,
-          encoding: encoding,
-          context: context,
-          onHijack: onHijack == null ? null : new _OnHijack(onHijack));
+            protocolVersion: protocolVersion,
+            headers: headers,
+            url: url,
+            handlerPath: handlerPath,
+            body: body,
+            encoding: encoding,
+            context: context,
+            onHijack: onHijack == null ? null : new _OnHijack(onHijack));
 
   /// This constructor has the same signature as [new Request] except that
   /// accepts [onHijack] as [_OnHijack].
@@ -154,13 +160,18 @@
   /// Any [Request] created by calling [change] will pass [_onHijack] from the
   /// source [Request] to ensure that [hijack] can only be called once, even
   /// from a changed [Request].
-  Request._(this.method, Uri requestedUri, {String protocolVersion,
-      Map<String, String> headers, String handlerPath, Uri url, body,
-      Encoding encoding, Map<String, Object> context, _OnHijack onHijack})
+  Request._(this.method, Uri requestedUri,
+      {String protocolVersion,
+      Map<String, String> headers,
+      String handlerPath,
+      Uri url,
+      body,
+      Encoding encoding,
+      Map<String, Object> context,
+      _OnHijack onHijack})
       : this.requestedUri = requestedUri,
-        this.protocolVersion = protocolVersion == null
-            ? '1.1'
-            : protocolVersion,
+        this.protocolVersion =
+            protocolVersion == null ? '1.1' : protocolVersion,
         this.url = _computeUrl(requestedUri, handlerPath, url),
         this.handlerPath = _computeHandlerPath(requestedUri, handlerPath, url),
         this._onHijack = onHijack,
@@ -207,8 +218,11 @@
   ///     request = request.change(path: "dir");
   ///     print(request.handlerPath); // => /static/dir/
   ///     print(request.url);        // => file.html
-  Request change({Map<String, String> headers, Map<String, Object> context,
-      String path, body}) {
+  Request change(
+      {Map<String, String> headers,
+      Map<String, Object> context,
+      String path,
+      body}) {
     headers = updateMap(this.headers, headers);
     context = updateMap(this.context, context);
 
diff --git a/pub/shelf/lib/src/response.dart b/pub/shelf/lib/src/response.dart
index a06bba9..67e028e 100644
--- a/pub/shelf/lib/src/response.dart
+++ b/pub/shelf/lib/src/response.dart
@@ -25,6 +25,7 @@
     _expiresCache = parseHttpDate(headers['expires']);
     return _expiresCache;
   }
+
   DateTime _expiresCache;
 
   /// The date and time the source of the response's data was last modified.
@@ -37,6 +38,7 @@
     _lastModifiedCache = parseHttpDate(headers['last-modified']);
     return _lastModifiedCache;
   }
+
   DateTime _lastModifiedCache;
 
   /// Constructs a 200 OK response.
@@ -57,10 +59,12 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response.ok(body, {Map<String, String> headers, Encoding encoding,
-    Map<String, Object> context})
-      : this(200, body: body, headers: headers, encoding: encoding,
-          context: context);
+  Response.ok(body,
+      {Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
+      : this(200,
+            body: body, headers: headers, encoding: encoding, context: context);
 
   /// Constructs a 301 Moved Permanently response.
   ///
@@ -82,10 +86,13 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response.movedPermanently(location, {body, Map<String, String> headers,
-      Encoding encoding, Map<String, Object> context})
+  Response.movedPermanently(location,
+      {body,
+      Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
       : this._redirect(301, location, body, headers, encoding,
-          context: context);
+            context: context);
 
   /// Constructs a 302 Found response.
   ///
@@ -107,10 +114,13 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response.found(location, {body, Map<String, String> headers,
-      Encoding encoding, Map<String, Object> context})
+  Response.found(location,
+      {body,
+      Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
       : this._redirect(302, location, body, headers, encoding,
-          context: context);
+            context: context);
 
   /// Constructs a 303 See Other response.
   ///
@@ -133,20 +143,23 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response.seeOther(location, {body, Map<String, String> headers,
-      Encoding encoding, Map<String, Object> context})
+  Response.seeOther(location,
+      {body,
+      Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
       : this._redirect(303, location, body, headers, encoding,
-          context: context);
+            context: context);
 
   /// Constructs a helper constructor for redirect responses.
   Response._redirect(int statusCode, location, body,
       Map<String, String> headers, Encoding encoding,
-      { Map<String, Object> context })
+      {Map<String, Object> context})
       : this(statusCode,
             body: body,
             encoding: encoding,
-            headers: addHeader(
-                headers, 'location', _locationToString(location)),
+            headers:
+                addHeader(headers, 'location', _locationToString(location)),
             context: context);
 
   /// Constructs a 304 Not Modified response.
@@ -155,10 +168,11 @@
   /// information used to determine whether the requested resource has changed
   /// since the last request. It indicates that the resource has not changed and
   /// the old value should be used.
-  Response.notModified({Map<String, String> headers,
-    Map<String, Object> context})
-      : this(304, headers: addHeader(
-            headers, 'date', formatHttpDate(new DateTime.now())),
+  Response.notModified(
+      {Map<String, String> headers, Map<String, Object> context})
+      : this(304,
+            headers:
+                addHeader(headers, 'date', formatHttpDate(new DateTime.now())),
             context: context);
 
   /// Constructs a 403 Forbidden response.
@@ -179,12 +193,14 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response.forbidden(body, {Map<String, String> headers,
-      Encoding encoding, Map<String, Object> context})
+  Response.forbidden(body,
+      {Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
       : this(403,
-          headers: body == null ? _adjustErrorHeaders(headers) : headers,
-          body: body == null ? 'Forbidden' : body,
-          context: context);
+            headers: body == null ? _adjustErrorHeaders(headers) : headers,
+            body: body == null ? 'Forbidden' : body,
+            context: context);
 
   /// Constructs a 404 Not Found response.
   ///
@@ -205,12 +221,14 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response.notFound(body, {Map<String, String> headers, Encoding encoding,
-    Map<String, Object> context})
+  Response.notFound(body,
+      {Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
       : this(404,
-          headers: body == null ? _adjustErrorHeaders(headers) : headers,
-          body: body == null ? 'Not Found' : body,
-          context: context);
+            headers: body == null ? _adjustErrorHeaders(headers) : headers,
+            body: body == null ? 'Not Found' : body,
+            context: context);
 
   /// Constructs a 500 Internal Server Error response.
   ///
@@ -231,8 +249,11 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response.internalServerError({body, Map<String, String> headers,
-      Encoding encoding, Map<String, Object> context})
+  Response.internalServerError(
+      {body,
+      Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
       : this(500,
             headers: body == null ? _adjustErrorHeaders(headers) : headers,
             body: body == null ? 'Internal Server Error' : body,
@@ -256,8 +277,11 @@
   /// If [encoding] is passed, the "encoding" field of the Content-Type header
   /// in [headers] will be set appropriately. If there is no existing
   /// Content-Type header, it will be set to "application/octet-stream".
-  Response(this.statusCode, {body, Map<String, String> headers,
-      Encoding encoding, Map<String, Object> context})
+  Response(this.statusCode,
+      {body,
+      Map<String, String> headers,
+      Encoding encoding,
+      Map<String, Object> context})
       : super(body, encoding: encoding, headers: headers, context: context) {
     if (statusCode < 100) {
       throw new ArgumentError("Invalid status code: $statusCode.");
@@ -286,8 +310,8 @@
 
     if (body == null) body = getBody(this);
 
-    return new Response(this.statusCode, body: body, headers: headers,
-        context: context);
+    return new Response(this.statusCode,
+        body: body, headers: headers, context: context);
   }
 }
 
diff --git a/pub/shelf/lib/src/server_handler.dart b/pub/shelf/lib/src/server_handler.dart
index fbe765a..eb5f6fd 100644
--- a/pub/shelf/lib/src/server_handler.dart
+++ b/pub/shelf/lib/src/server_handler.dart
@@ -82,7 +82,7 @@
   }
 
   Future close() => _closeMemo.runOnce(() {
-    return _onClose == null ? null : _onClose();
-  });
+        return _onClose == null ? null : _onClose();
+      });
   final _closeMemo = new AsyncMemoizer();
 }
diff --git a/pub/shelf/lib/src/util.dart b/pub/shelf/lib/src/util.dart
index fcf66d8..0ebf839 100644
--- a/pub/shelf/lib/src/util.dart
+++ b/pub/shelf/lib/src/util.dart
@@ -32,8 +32,8 @@
 /// [updates] is used.
 ///
 /// If [updates] is `null` or empty, [original] is returned unchanged.
-Map/*<K, V>*/ updateMap/*<K, V>*/(Map/*<K, V>*/ original,
-    Map/*<K, V>*/ updates) {
+Map/*<K, V>*/ updateMap/*<K, V>*/(
+    Map/*<K, V>*/ original, Map/*<K, V>*/ updates) {
   if (updates == null || updates.isEmpty) return original;
 
   return new Map.from(original)..addAll(updates);
diff --git a/pub/shelf/pubspec.yaml b/pub/shelf/pubspec.yaml
index c331e58..f1d3604 100644
--- a/pub/shelf/pubspec.yaml
+++ b/pub/shelf/pubspec.yaml
@@ -1,5 +1,5 @@
 name: shelf
-version: 0.6.7+2
+version: 0.6.8
 author: Dart Team <misc@dartlang.org>
 description: Web Server Middleware for Dart
 homepage: https://github.com/dart-lang/shelf
@@ -15,4 +15,4 @@
 dev_dependencies:
   http: '>=0.9.2 <0.12.0'
   scheduled_test: '^0.12.0'
-  test: '^0.12.0'
+  test: '^0.12.7'
diff --git a/pub/shelf/tool/travis.sh b/pub/shelf/tool/travis.sh
deleted file mode 100755
index 6604af3..0000000
--- a/pub/shelf/tool/travis.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-# Fast fail the script on failures.
-set -e
-
-pub run test -p vm,content-shell,firefox -j 1
-
-# Install dart_coveralls; gather and send coverage data.
-if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then
-  pub global activate dart_coveralls
-
-  pub global run dart_coveralls report \
-    --exclude-test-files \
-    test/test_all.dart
-fi
diff --git a/pub/shelf_static/.test_config b/pub/shelf_static/.test_config
new file mode 100644
index 0000000..632d153
--- /dev/null
+++ b/pub/shelf_static/.test_config
@@ -0,0 +1,5 @@
+{
+  "test_package": {
+    "platforms": ["vm"]
+  }
+}
diff --git a/pub/shelf_static/.travis.yml b/pub/shelf_static/.travis.yml
index e110e4e..93b8adb 100644
--- a/pub/shelf_static/.travis.yml
+++ b/pub/shelf_static/.travis.yml
@@ -1,6 +1,14 @@
 language: dart
 sudo: false
 dart:
-  - stable
   - dev
-script: ./tool/travis.sh
+  - stable
+  - 1.23.0
+  - 1.22.1
+cache:
+  directories:
+    - $HOME/.pub-cache
+dart_task:
+  - test: --platform vm
+  - dartfmt
+  - dartanalyzer
diff --git a/pub/shelf_static/BUILD.gn b/pub/shelf_static/BUILD.gn
index 123fdc4..3591d0f 100644
--- a/pub/shelf_static/BUILD.gn
+++ b/pub/shelf_static/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for shelf_static-0.2.4
+# This file is generated by importer.py for shelf_static-0.2.5
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/shelf_static/CHANGELOG.md b/pub/shelf_static/CHANGELOG.md
index 53c712c..e725bda 100644
--- a/pub/shelf_static/CHANGELOG.md
+++ b/pub/shelf_static/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.5
+
+* Add an optional `contentTypeResolver` argument to `createStaticHandler`.
+
 ## 0.2.4
 
 * Add support for "sniffing" the content of the file for the content-type via an optional
@@ -64,7 +68,7 @@
 * The preferred top-level method is now `createStaticHandler`. `getHandler` is deprecated.
 * Set `content-type` header if the mime type of the requested file can be determined from the file extension.
 * Respond with `304-Not modified` against `IF-MODIFIED-SINCE` request header.
-* Better error when provided a non-existant `fileSystemPath`.
+* Better error when provided a non-existent `fileSystemPath`.
 * Added `example/example_server.dart`.
 
 ## 0.1.1+1
diff --git a/pub/shelf_static/README.md b/pub/shelf_static/README.md
index ffe0e26..b0bf77d 100644
--- a/pub/shelf_static/README.md
+++ b/pub/shelf_static/README.md
@@ -1,7 +1,6 @@
 `shelf_static` is a `Handler` for the Dart `shelf` package.
 
 [![Build Status](https://travis-ci.org/dart-lang/shelf_static.svg?branch=master)](https://travis-ci.org/dart-lang/shelf_static?branch=master)
-[![Coverage Status](https://coveralls.io/repos/dart-lang/shelf_static/badge.svg?branch=master&service=github)](https://coveralls.io/github/dart-lang/shelf_static?branch=master)
 
 ### Example
 ```dart
diff --git a/pub/shelf_static/.analysis_options b/pub/shelf_static/analysis_options.yaml
similarity index 100%
rename from pub/shelf_static/.analysis_options
rename to pub/shelf_static/analysis_options.yaml
diff --git a/pub/shelf_static/example/example_server.dart b/pub/shelf_static/example/example_server.dart
index 1233eef..087b421 100644
--- a/pub/shelf_static/example/example_server.dart
+++ b/pub/shelf_static/example/example_server.dart
@@ -60,6 +60,7 @@
       abbr: 'f',
       defaultsTo: false,
       negatable: false,
-      help: 'List the files in the source directory instead of servering the default document - "$_defaultDoc".');
+      help: 'List the files in the source directory instead of serving the '
+          'default document - "$_defaultDoc".');
 
 const _defaultDoc = 'index.html';
diff --git a/pub/shelf_static/lib/src/directory_listing.dart b/pub/shelf_static/lib/src/directory_listing.dart
index 8339fb9..a391a52 100644
--- a/pub/shelf_static/lib/src/directory_listing.dart
+++ b/pub/shelf_static/lib/src/directory_listing.dart
@@ -77,9 +77,12 @@
     controller.add(encoding.encode(string));
   }
 
-  String heading = path.relative(dirPath, from: fileSystemPath);
-  if (heading == '.') heading = '/';
-  else heading = '/$heading/';
+  var heading = path.relative(dirPath, from: fileSystemPath);
+  if (heading == '.') {
+    heading = '/';
+  } else {
+    heading = '/$heading/';
+  }
 
   add(_getHeader(sanitizer.convert(heading)));
   new Directory(dirPath).list().listen((FileSystemEntity entity) {
diff --git a/pub/shelf_static/lib/src/static_handler.dart b/pub/shelf_static/lib/src/static_handler.dart
index a2a1b5c..9f67de9 100644
--- a/pub/shelf_static/lib/src/static_handler.dart
+++ b/pub/shelf_static/lib/src/static_handler.dart
@@ -32,11 +32,15 @@
 ///
 /// If [useHeaderBytesForContentType] is `true`, the contents of the
 /// file will be used along with the file path to determine the content type.
+///
+/// Specify a custom [contentTypeResolver] to customize automatic content type
+/// detection.
 Handler createStaticHandler(String fileSystemPath,
     {bool serveFilesOutsidePath: false,
     String defaultDocument,
     bool listDirectories: false,
-    bool useHeaderBytesForContentType: false}) {
+    bool useHeaderBytesForContentType: false,
+    mime.MimeTypeResolver contentTypeResolver}) {
   var rootDir = new Directory(fileSystemPath);
   if (!rootDir.existsSync()) {
     throw new ArgumentError('A directory corresponding to fileSystemPath '
@@ -51,6 +55,8 @@
     }
   }
 
+  contentTypeResolver ??= new mime.MimeTypeResolver();
+
   return (Request request) async {
     var segs = [fileSystemPath]..addAll(request.url.pathSegments);
 
@@ -58,7 +64,7 @@
 
     var entityType = FileSystemEntity.typeSync(fsPath, followLinks: true);
 
-    File file = null;
+    File file;
 
     if (entityType == FileSystemEntityType.FILE) {
       file = new File(fsPath);
@@ -109,16 +115,17 @@
 
     String contentType;
     if (useHeaderBytesForContentType) {
-      var length =
-          math.min(mime.defaultMagicNumbersMaxLength, file.lengthSync());
+      var length = math.min(
+          contentTypeResolver.magicNumbersMaxLength, file.lengthSync());
 
       var byteSink = new ByteAccumulatorSink();
 
       await file.openRead(0, length).listen(byteSink.add).asFuture();
 
-      contentType = mime.lookupMimeType(file.path, headerBytes: byteSink.bytes);
+      contentType =
+          contentTypeResolver.lookup(file.path, headerBytes: byteSink.bytes);
     } else {
-      contentType = mime.lookupMimeType(file.path);
+      contentType = contentTypeResolver.lookup(file.path);
     }
 
     if (contentType != null) {
diff --git a/pub/shelf_static/pubspec.yaml b/pub/shelf_static/pubspec.yaml
index f1cc8d4..2618b35 100644
--- a/pub/shelf_static/pubspec.yaml
+++ b/pub/shelf_static/pubspec.yaml
@@ -1,5 +1,5 @@
 name: shelf_static
-version: 0.2.4
+version: 0.2.5
 author: Dart Team <misc@dartlang.org>
 description: Static file server support for Shelf
 homepage: https://github.com/dart-lang/shelf_static
diff --git a/pub/shelf_static/tool/travis.sh b/pub/shelf_static/tool/travis.sh
deleted file mode 100755
index 0f7c725..0000000
--- a/pub/shelf_static/tool/travis.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-# Fast fail the script on failures.
-set -e
-
-pub run test
-
-# Install dart_coveralls; gather and send coverage data.
-if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then
-  pub global activate dart_coveralls
-  pub global run dart_coveralls report \
-    --exclude-test-files \
-    --log-level warning \
-    test/test_all.dart
-fi
diff --git a/pub/stack_trace/.travis.yml b/pub/stack_trace/.travis.yml
new file mode 100644
index 0000000..fff8494
--- /dev/null
+++ b/pub/stack_trace/.travis.yml
@@ -0,0 +1,22 @@
+language: dart
+sudo: false
+dart:
+  - dev
+  - stable
+  - 1.22.1
+  - 1.21.1
+dart_task:
+  - test: -p vm
+  - test: -p firefox
+  - test: -p dartium
+    install_dartium: true
+  - dartanalyzer
+matrix:
+  include:
+    # Only validate formatting using the dev release
+    # Formatted with 1.23.0+ which has (good) changes since 1.22.1
+    - dart: dev
+      dart_task: dartfmt
+cache:
+  directories:
+    - $HOME/.pub-cache
diff --git a/pub/stack_trace/BUILD.gn b/pub/stack_trace/BUILD.gn
index 224c8a3..3ab3f98 100644
--- a/pub/stack_trace/BUILD.gn
+++ b/pub/stack_trace/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for stack_trace-1.7.3
+# This file is generated by importer.py for stack_trace-1.7.4
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/stack_trace/CHANGELOG.md b/pub/stack_trace/CHANGELOG.md
index 5e56d8d..abb5b0a 100644
--- a/pub/stack_trace/CHANGELOG.md
+++ b/pub/stack_trace/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.7.4
+
+* Always run `onError` callbacks for `Chain.capture()` in the parent zone.
+
 ## 1.7.3
 
 * Fix broken links in the README.
diff --git a/pub/stack_trace/.analysis_options b/pub/stack_trace/analysis_options.yaml
similarity index 100%
rename from pub/stack_trace/.analysis_options
rename to pub/stack_trace/analysis_options.yaml
diff --git a/pub/stack_trace/lib/src/chain.dart b/pub/stack_trace/lib/src/chain.dart
index 4543eff..e93b2b4 100644
--- a/pub/stack_trace/lib/src/chain.dart
+++ b/pub/stack_trace/lib/src/chain.dart
@@ -70,7 +70,7 @@
   /// considered unhandled.
   ///
   /// If [callback] returns a value, it will be returned by [capture] as well.
-  static /*=T*/ capture/*<T>*/(/*=T*/ callback(),
+  static T capture<T>(T callback(),
       {void onError(error, Chain chain), bool when: true}) {
     if (!when) {
       var newOnError;
@@ -95,24 +95,18 @@
         // TODO(nweiz): Don't special-case this when issue 19566 is fixed.
         return Zone.current.handleUncaughtError(error, stackTrace);
       }
-    }, zoneSpecification: spec.toSpec(), zoneValues: {
-      _specKey: spec,
-      StackZoneSpecification.disableKey: false
-    }) as dynamic/*=T*/;
-    // TODO(rnystrom): Remove this cast if runZoned() gets a generic type.
+    },
+        zoneSpecification: spec.toSpec(),
+        zoneValues: {_specKey: spec, StackZoneSpecification.disableKey: false});
   }
 
   /// If [when] is `true` and this is called within a [Chain.capture] zone, runs
   /// [callback] in a [Zone] in which chain capturing is disabled.
   ///
   /// If [callback] returns a value, it will be returned by [disable] as well.
-  static /*=T*/ disable/*<T>*/(/*=T*/ callback(), {bool when: true}) {
-    var zoneValues = when
-        ? {
-            _specKey: null,
-            StackZoneSpecification.disableKey: true
-          }
-        : null;
+  static/*=T*/ disable/*<T>*/(/*=T*/ callback(), {bool when: true}) {
+    var zoneValues =
+        when ? {_specKey: null, StackZoneSpecification.disableKey: true} : null;
 
     return runZoned(callback, zoneValues: zoneValues);
   }
@@ -133,15 +127,15 @@
   ///
   /// If this is called outside of a [capture] zone, it just returns a
   /// single-trace chain.
-  factory Chain.current([int level=0]) {
+  factory Chain.current([int level = 0]) {
     if (_currentSpec != null) return _currentSpec.currentChain(level + 1);
 
     var chain = new Chain.forTrace(StackTrace.current);
     return new LazyChain(() {
       // JS includes a frame for the call to StackTrace.current, but the VM
       // doesn't, so we skip an extra frame in a JS context.
-      var first = new Trace(
-          chain.traces.first.frames.skip(level + (inJS ? 2 : 1)));
+      var first =
+          new Trace(chain.traces.first.frames.skip(level + (inJS ? 2 : 1)));
       return new Chain([first]..addAll(chain.traces.skip(1)));
     });
   }
@@ -178,8 +172,7 @@
   }
 
   /// Returns a new [Chain] comprised of [traces].
-  Chain(Iterable<Trace> traces)
-      : traces = new List<Trace>.unmodifiable(traces);
+  Chain(Iterable<Trace> traces) : traces = new List<Trace>.unmodifiable(traces);
 
   /// Returns a terser version of [this].
   ///
@@ -208,8 +201,8 @@
   /// library or from this package, and simplify core library frames as in
   /// [Trace.terse].
   Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) {
-    var foldedTraces = traces.map(
-        (trace) => trace.foldFrames(predicate, terse: terse));
+    var foldedTraces =
+        traces.map((trace) => trace.foldFrames(predicate, terse: terse));
     var nonEmptyTraces = foldedTraces.where((trace) {
       // Ignore traces that contain only folded frames.
       if (trace.frames.length > 1) return true;
@@ -240,7 +233,8 @@
   String toString() {
     // Figure out the longest path so we know how much to pad.
     var longest = traces.map((trace) {
-      return trace.frames.map((frame) => frame.location.length)
+      return trace.frames
+          .map((frame) => frame.location.length)
           .fold(0, math.max);
     }).fold(0, math.max);
 
diff --git a/pub/stack_trace/lib/src/frame.dart b/pub/stack_trace/lib/src/frame.dart
index 8599245..bbe5c79 100644
--- a/pub/stack_trace/lib/src/frame.dart
+++ b/pub/stack_trace/lib/src/frame.dart
@@ -17,8 +17,8 @@
 //     at VW.call$0 (eval as fn
 //         (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28)
 //     at http://pub.dartlang.org/stuff.dart.js:560:28
-final _v8Frame = new RegExp(
-    r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$');
+final _v8Frame =
+    new RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$');
 
 // http://pub.dartlang.org/stuff.dart.js:560:28
 final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)|native$');
@@ -27,36 +27,34 @@
 // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28)
 // eval as function (eval as otherFunction
 //     (http://pub.dartlang.org/stuff.dart.js:560:28))
-final _v8EvalLocation = new RegExp(
-    r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$');
+final _v8EvalLocation =
+    new RegExp(r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$');
 
 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560
 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560
 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560
 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560:36
 // http://pub.dartlang.org/stuff.dart.js:560
-final _firefoxSafariFrame = new RegExp(
-    r'^'
+final _firefoxSafariFrame = new RegExp(r'^'
     r'(?:' // Member description. Not present in some Safari frames.
-      r'([^@(/]*)' // The actual name of the member.
-      r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox.
-      r'((?:/[^/]*)*)' // Extra characters indicating a nested closure.
-      r'(?:\(.*\))?' // Arguments to the closure.
-      r'@'
+    r'([^@(/]*)' // The actual name of the member.
+    r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox.
+    r'((?:/[^/]*)*)' // Extra characters indicating a nested closure.
+    r'(?:\(.*\))?' // Arguments to the closure.
+    r'@'
     r')?'
     r'(.*?)' // The frame's URL.
     r':'
     r'(\d*)' // The line number. Empty in Safari if it's unknown.
     r'(?::(\d*))?' // The column number. Not present in older browsers and
-                   // empty in Safari if it's unknown.
+    // empty in Safari if it's unknown.
     r'$');
 
 // foo/bar.dart 10:11 Foo._bar
 // foo/bar.dart 10:11 (anonymous function).dart.fn
 // http://dartlang.org/foo/bar.dart Foo._bar
 // data:... 10:11 Foo._bar
-final _friendlyFrame = new RegExp(
-    r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$');
+final _friendlyFrame = new RegExp(r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$');
 
 /// A regular expression that matches asynchronous member names generated by the
 /// VM.
@@ -120,7 +118,7 @@
   /// By default, this will return the frame above the current method. If
   /// [level] is `0`, it will return the current method's frame; if [level] is
   /// higher than `1`, it will return higher frames.
-  factory Frame.caller([int level=1]) {
+  factory Frame.caller([int level = 1]) {
     if (level < 0) {
       throw new ArgumentError("Argument [level] must be greater than or equal "
           "to 0.");
@@ -131,71 +129,72 @@
 
   /// Parses a string representation of a Dart VM stack frame.
   factory Frame.parseVM(String frame) => _catchFormatException(frame, () {
-    // The VM sometimes folds multiple stack frames together and replaces them
-    // with "...".
-    if (frame == '...') {
-      return new Frame(new Uri(), null, null, '...');
-    }
+        // The VM sometimes folds multiple stack frames together and replaces them
+        // with "...".
+        if (frame == '...') {
+          return new Frame(new Uri(), null, null, '...');
+        }
 
-    var match = _vmFrame.firstMatch(frame);
-    if (match == null) return new UnparsedFrame(frame);
+        var match = _vmFrame.firstMatch(frame);
+        if (match == null) return new UnparsedFrame(frame);
 
-    // Get the pieces out of the regexp match. Function, URI and line should
-    // always be found. The column is optional.
-    var member = match[1]
-        .replaceAll(_asyncBody, "<async>")
-        .replaceAll("<anonymous closure>", "<fn>");
-    var uri = Uri.parse(match[2]);
+        // Get the pieces out of the regexp match. Function, URI and line should
+        // always be found. The column is optional.
+        var member = match[1]
+            .replaceAll(_asyncBody, "<async>")
+            .replaceAll("<anonymous closure>", "<fn>");
+        var uri = Uri.parse(match[2]);
 
-    var lineAndColumn = match[3].split(':');
-    var line = lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null;
-    var column = lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null;
-    return new Frame(uri, line, column, member);
-  });
+        var lineAndColumn = match[3].split(':');
+        var line =
+            lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null;
+        var column =
+            lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null;
+        return new Frame(uri, line, column, member);
+      });
 
   /// Parses a string representation of a Chrome/V8 stack frame.
   factory Frame.parseV8(String frame) => _catchFormatException(frame, () {
-    var match = _v8Frame.firstMatch(frame);
-    if (match == null) return new UnparsedFrame(frame);
+        var match = _v8Frame.firstMatch(frame);
+        if (match == null) return new UnparsedFrame(frame);
 
-    // v8 location strings can be arbitrarily-nested, since it adds a layer of
-    // nesting for each eval performed on that line.
-    parseLocation(location, member) {
-      var evalMatch = _v8EvalLocation.firstMatch(location);
-      while (evalMatch != null) {
-        location = evalMatch[1];
-        evalMatch = _v8EvalLocation.firstMatch(location);
-      }
+        // v8 location strings can be arbitrarily-nested, since it adds a layer of
+        // nesting for each eval performed on that line.
+        parseLocation(location, member) {
+          var evalMatch = _v8EvalLocation.firstMatch(location);
+          while (evalMatch != null) {
+            location = evalMatch[1];
+            evalMatch = _v8EvalLocation.firstMatch(location);
+          }
 
-      if (location == 'native') {
-        return new Frame(Uri.parse('native'), null, null, member);
-      }
+          if (location == 'native') {
+            return new Frame(Uri.parse('native'), null, null, member);
+          }
 
-      var urlMatch = _v8UrlLocation.firstMatch(location);
-      if (urlMatch == null) return new UnparsedFrame(frame);
+          var urlMatch = _v8UrlLocation.firstMatch(location);
+          if (urlMatch == null) return new UnparsedFrame(frame);
 
-      return new Frame(
-          _uriOrPathToUri(urlMatch[1]),
-          int.parse(urlMatch[2]),
-          int.parse(urlMatch[3]),
-          member);
-    }
+          return new Frame(_uriOrPathToUri(urlMatch[1]), int.parse(urlMatch[2]),
+              int.parse(urlMatch[3]), member);
+        }
 
-    // V8 stack frames can be in two forms.
-    if (match[2] != null) {
-      // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists
-      // anonymous functions within eval as "<anonymous>", while IE10 lists them
-      // as "Anonymous function".
-      return parseLocation(match[2],
-          match[1].replaceAll("<anonymous>", "<fn>")
+        // V8 stack frames can be in two forms.
+        if (match[2] != null) {
+          // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists
+          // anonymous functions within eval as "<anonymous>", while IE10 lists them
+          // as "Anonymous function".
+          return parseLocation(
+              match[2],
+              match[1]
+                  .replaceAll("<anonymous>", "<fn>")
                   .replaceAll("Anonymous function", "<fn>")
                   .replaceAll("(anonymous function)", "<fn>"));
-    } else {
-      // The second form looks like " at LOCATION", and is used for anonymous
-      // functions.
-      return parseLocation(match[3], "<fn>");
-    }
-  });
+        } else {
+          // The second form looks like " at LOCATION", and is used for anonymous
+          // functions.
+          return parseLocation(match[3], "<fn>");
+        }
+      });
 
   /// Parses a string representation of a JavaScriptCore stack trace.
   factory Frame.parseJSCore(String frame) => new Frame.parseV8(frame);
@@ -208,31 +207,31 @@
 
   /// Parses a string representation of a Firefox stack frame.
   factory Frame.parseFirefox(String frame) => _catchFormatException(frame, () {
-    var match = _firefoxSafariFrame.firstMatch(frame);
-    if (match == null) return new UnparsedFrame(frame);
+        var match = _firefoxSafariFrame.firstMatch(frame);
+        if (match == null) return new UnparsedFrame(frame);
 
-    // Normally this is a URI, but in a jsshell trace it can be a path.
-    var uri = _uriOrPathToUri(match[3]);
+        // Normally this is a URI, but in a jsshell trace it can be a path.
+        var uri = _uriOrPathToUri(match[3]);
 
-    var member;
-    if (match[1] != null) {
-      member = match[1];
-      member +=
-          new List.filled('/'.allMatches(match[2]).length, ".<fn>").join();
-      if (member == '') member = '<fn>';
+        var member;
+        if (match[1] != null) {
+          member = match[1];
+          member +=
+              new List.filled('/'.allMatches(match[2]).length, ".<fn>").join();
+          if (member == '') member = '<fn>';
 
-      // Some Firefox members have initial dots. We remove them for consistency
-      // with other platforms.
-      member = member.replaceFirst(_initialDot, '');
-    } else {
-      member = '<fn>';
-    }
+          // Some Firefox members have initial dots. We remove them for consistency
+          // with other platforms.
+          member = member.replaceFirst(_initialDot, '');
+        } else {
+          member = '<fn>';
+        }
 
-    var line = match[4] == '' ? null : int.parse(match[4]);
-    var column = match[5] == null || match[5] == '' ?
-        null : int.parse(match[5]);
-    return new Frame(uri, line, column, member);
-  });
+        var line = match[4] == '' ? null : int.parse(match[4]);
+        var column =
+            match[5] == null || match[5] == '' ? null : int.parse(match[5]);
+        return new Frame(uri, line, column, member);
+      });
 
   /// Parses a string representation of a Safari 6.0 stack frame.
   @Deprecated("Use Frame.parseSafari instead.")
@@ -247,26 +246,26 @@
 
   /// Parses this package's string representation of a stack frame.
   factory Frame.parseFriendly(String frame) => _catchFormatException(frame, () {
-    var match = _friendlyFrame.firstMatch(frame);
-    if (match == null) {
-      throw new FormatException(
-          "Couldn't parse package:stack_trace stack trace line '$frame'.");
-    }
-    // Fake truncated data urls generated by the friendly stack trace format
-    // cause Uri.parse to throw an exception so we have to special case them.
-    var uri = match[1] == 'data:...'
-        ? new Uri.dataFromString('')
-        : Uri.parse(match[1]);
-    // If there's no scheme, this is a relative URI. We should interpret it as
-    // relative to the current working directory.
-    if (uri.scheme == '') {
-      uri = path.toUri(path.absolute(path.fromUri(uri)));
-    }
+        var match = _friendlyFrame.firstMatch(frame);
+        if (match == null) {
+          throw new FormatException(
+              "Couldn't parse package:stack_trace stack trace line '$frame'.");
+        }
+        // Fake truncated data urls generated by the friendly stack trace format
+        // cause Uri.parse to throw an exception so we have to special case them.
+        var uri = match[1] == 'data:...'
+            ? new Uri.dataFromString('')
+            : Uri.parse(match[1]);
+        // If there's no scheme, this is a relative URI. We should interpret it as
+        // relative to the current working directory.
+        if (uri.scheme == '') {
+          uri = path.toUri(path.absolute(path.fromUri(uri)));
+        }
 
-    var line = match[2] == null ? null : int.parse(match[2]);
-    var column = match[3] == null ? null : int.parse(match[3]);
-    return new Frame(uri, line, column, match[4]);
-  });
+        var line = match[2] == null ? null : int.parse(match[2]);
+        var column = match[3] == null ? null : int.parse(match[3]);
+        return new Frame(uri, line, column, match[4]);
+      });
 
   /// A regular expression matching an absolute URI.
   static final _uriRegExp = new RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://');
diff --git a/pub/stack_trace/lib/src/lazy_trace.dart b/pub/stack_trace/lib/src/lazy_trace.dart
index 618f007..97bb391 100644
--- a/pub/stack_trace/lib/src/lazy_trace.dart
+++ b/pub/stack_trace/lib/src/lazy_trace.dart
@@ -26,7 +26,7 @@
   StackTrace get vmTrace => _trace.vmTrace;
   Trace get terse => new LazyTrace(() => _trace.terse);
   Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) =>
-    new LazyTrace(() => _trace.foldFrames(predicate, terse: terse));
+      new LazyTrace(() => _trace.foldFrames(predicate, terse: terse));
   String toString() => _trace.toString();
 
   // Work around issue 14075.
diff --git a/pub/stack_trace/lib/src/stack_zone_specification.dart b/pub/stack_trace/lib/src/stack_zone_specification.dart
index 948ef30..924f2ef 100644
--- a/pub/stack_trace/lib/src/stack_zone_specification.dart
+++ b/pub/stack_trace/lib/src/stack_zone_specification.dart
@@ -77,7 +77,7 @@
   /// By default, the first frame of the first trace will be the line where
   /// [currentChain] is called. If [level] is passed, the first trace will start
   /// that many frames up instead.
-  Chain currentChain([int level=0]) => _createNode(level + 1).toChain();
+  Chain currentChain([int level = 0]) => _createNode(level + 1).toChain();
 
   /// Returns the stack chain associated with [trace], if one exists.
   ///
@@ -92,8 +92,8 @@
 
   /// Tracks the current stack chain so it can be set to [_currentChain] when
   /// [f] is run.
-  ZoneCallback _registerCallback(Zone self, ZoneDelegate parent, Zone zone,
-      Function f) {
+  ZoneCallback _registerCallback(
+      Zone self, ZoneDelegate parent, Zone zone, Function f) {
     if (f == null || _disabled) return parent.registerCallback(zone, f);
     var node = _createNode(1);
     return parent.registerCallback(zone, () => _run(f, node));
@@ -101,8 +101,8 @@
 
   /// Tracks the current stack chain so it can be set to [_currentChain] when
   /// [f] is run.
-  ZoneUnaryCallback _registerUnaryCallback(Zone self, ZoneDelegate parent,
-      Zone zone, Function f) {
+  ZoneUnaryCallback _registerUnaryCallback(
+      Zone self, ZoneDelegate parent, Zone zone, Function f) {
     if (f == null || _disabled) return parent.registerUnaryCallback(zone, f);
     var node = _createNode(1);
     return parent.registerUnaryCallback(zone, (arg) {
@@ -112,8 +112,8 @@
 
   /// Tracks the current stack chain so it can be set to [_currentChain] when
   /// [f] is run.
-  ZoneBinaryCallback _registerBinaryCallback(Zone self, ZoneDelegate parent,
-      Zone zone, Function f) {
+  ZoneBinaryCallback _registerBinaryCallback(
+      Zone self, ZoneDelegate parent, Zone zone, Function f) {
     if (f == null || _disabled) return parent.registerBinaryCallback(zone, f);
 
     var node = _createNode(1);
@@ -124,8 +124,8 @@
 
   /// Looks up the chain associated with [stackTrace] and passes it either to
   /// [_onError] or [parent]'s error handler.
-  _handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, error,
-      StackTrace stackTrace) {
+  _handleUncaughtError(
+      Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) {
     if (_disabled) {
       return parent.handleUncaughtError(zone, error, stackTrace);
     }
@@ -138,7 +138,7 @@
     // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just
     // allow [runBinary] to throw instead once issue 18134 is fixed.
     try {
-      return parent.runBinary(zone, _onError, error, stackChain);
+      return self.parent.runBinary(_onError, error, stackChain);
     } catch (newError, newStackTrace) {
       if (identical(newError, error)) {
         return parent.handleUncaughtError(zone, error, stackChain);
@@ -171,8 +171,8 @@
   /// By default, the first frame of the first trace will be the line where
   /// [_createNode] is called. If [level] is passed, the first trace will start
   /// that many frames up instead.
-  _Node _createNode([int level=0]) =>
-    new _Node(_currentTrace(level + 1), _currentNode);
+  _Node _createNode([int level = 0]) =>
+      new _Node(_currentTrace(level + 1), _currentNode);
 
   // TODO(nweiz): use a more robust way of detecting and tracking errors when
   // issue 15105 is fixed.
diff --git a/pub/stack_trace/lib/src/trace.dart b/pub/stack_trace/lib/src/trace.dart
index 9edee6e..6296df5 100644
--- a/pub/stack_trace/lib/src/trace.dart
+++ b/pub/stack_trace/lib/src/trace.dart
@@ -43,16 +43,17 @@
 final _firefoxSafariTrace = new RegExp(
     r"^"
     r"(" // Member description. Not present in some Safari frames.
-      r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments.
-      r"@"
+    r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments.
+    r"@"
     r")?"
     r"[^\s]*" // Frame URL.
     r":\d*" // Line or column number. Some older frames only have a line number.
-    r"$", multiLine: true);
+    r"$",
+    multiLine: true);
 
 /// A RegExp to match this package's stack traces.
-final _friendlyTrace = new RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$",
-    multiLine: true);
+final _friendlyTrace =
+    new RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", multiLine: true);
 
 /// A stack trace, comprised of a list of stack frames.
 class Trace implements StackTrace {
@@ -74,7 +75,7 @@
   /// By default, the first frame of this trace will be the line where
   /// [Trace.current] is called. If [level] is passed, the trace will start that
   /// many frames up instead.
-  factory Trace.current([int level=0]) {
+  factory Trace.current([int level = 0]) {
     if (level < 0) {
       throw new ArgumentError("Argument [level] must be greater than or equal "
           "to 0.");
@@ -133,14 +134,14 @@
   }
 
   /// Parses a string representation of a Dart VM stack trace.
-  Trace.parseVM(String trace)
-      : this(_parseVM(trace));
+  Trace.parseVM(String trace) : this(_parseVM(trace));
 
   static List<Frame> _parseVM(String trace) {
     // Ignore [vmChainGap]. This matches the behavior of
     // `Chain.parse().toTrace()`.
     var lines = trace.trim().replaceAll(vmChainGap, '').split("\n");
-    var frames = lines.take(lines.length - 1)
+    var frames = lines
+        .take(lines.length - 1)
         .map((line) => new Frame.parseVM(line))
         .toList();
 
@@ -154,16 +155,19 @@
 
   /// Parses a string representation of a Chrome/V8 stack trace.
   Trace.parseV8(String trace)
-      : this(trace.split("\n").skip(1)
-          // It's possible that an Exception's description contains a line that
-          // looks like a V8 trace line, which will screw this up.
-          // Unfortunately, that's impossible to detect.
-          .skipWhile((line) => !line.startsWith(_v8TraceLine))
-          .map((line) => new Frame.parseV8(line)));
+      : this(trace
+            .split("\n")
+            .skip(1)
+            // It's possible that an Exception's description contains a line that
+            // looks like a V8 trace line, which will screw this up.
+            // Unfortunately, that's impossible to detect.
+            .skipWhile((line) => !line.startsWith(_v8TraceLine))
+            .map((line) => new Frame.parseV8(line)));
 
   /// Parses a string representation of a JavaScriptCore stack trace.
   Trace.parseJSCore(String trace)
-      : this(trace.split("\n")
+      : this(trace
+            .split("\n")
             .where((line) => line != "\tat ")
             .map((line) => new Frame.parseV8(line)));
 
@@ -171,30 +175,31 @@
   ///
   /// IE10+ traces look just like V8 traces. Prior to IE10, stack traces can't
   /// be retrieved.
-  Trace.parseIE(String trace)
-      : this.parseV8(trace);
+  Trace.parseIE(String trace) : this.parseV8(trace);
 
   /// Parses a string representation of a Firefox stack trace.
   Trace.parseFirefox(String trace)
-      : this(trace.trim().split("\n")
-          .where((line) => line.isNotEmpty && line != '[native code]')
-          .map((line) => new Frame.parseFirefox(line)));
+      : this(trace
+            .trim()
+            .split("\n")
+            .where((line) => line.isNotEmpty && line != '[native code]')
+            .map((line) => new Frame.parseFirefox(line)));
 
   /// Parses a string representation of a Safari stack trace.
-  Trace.parseSafari(String trace)
-      : this.parseFirefox(trace);
+  Trace.parseSafari(String trace) : this.parseFirefox(trace);
 
   /// Parses a string representation of a Safari 6.1+ stack trace.
   @Deprecated("Use Trace.parseSafari instead.")
-  Trace.parseSafari6_1(String trace)
-      : this.parseSafari(trace);
+  Trace.parseSafari6_1(String trace) : this.parseSafari(trace);
 
   /// Parses a string representation of a Safari 6.0 stack trace.
   @Deprecated("Use Trace.parseSafari instead.")
   Trace.parseSafari6_0(String trace)
-      : this(trace.trim().split("\n")
-          .where((line) => line != '[native code]')
-          .map((line) => new Frame.parseFirefox(line)));
+      : this(trace
+            .trim()
+            .split("\n")
+            .where((line) => line != '[native code]')
+            .map((line) => new Frame.parseFirefox(line)));
 
   /// Parses this package's string representation of a stack trace.
   ///
@@ -203,14 +208,15 @@
   Trace.parseFriendly(String trace)
       : this(trace.isEmpty
             ? []
-            : trace.trim().split("\n")
+            : trace
+                .trim()
+                .split("\n")
                 // Filter out asynchronous gaps from [Chain]s.
                 .where((line) => !line.startsWith('====='))
                 .map((line) => new Frame.parseFriendly(line)));
 
   /// Returns a new [Trace] comprised of [frames].
-  Trace(Iterable<Frame> frames)
-      : frames = new List<Frame>.unmodifiable(frames);
+  Trace(Iterable<Frame> frames) : frames = new List<Frame>.unmodifiable(frames);
 
   /// Returns a VM-style [StackTrace] object.
   ///
@@ -274,8 +280,8 @@
       if (frame is UnparsedFrame || !predicate(frame)) {
         newFrames.add(frame);
       } else if (newFrames.isEmpty || !predicate(newFrames.last)) {
-        newFrames.add(new Frame(
-            frame.uri, frame.line, frame.column, frame.member));
+        newFrames
+            .add(new Frame(frame.uri, frame.line, frame.column, frame.member));
       }
     }
 
@@ -297,8 +303,8 @@
   /// Returns a human-readable string representation of [this].
   String toString() {
     // Figure out the longest path so we know how much to pad.
-    var longest = frames.map((frame) => frame.location.length)
-        .fold(0, math.max);
+    var longest =
+        frames.map((frame) => frame.location.length).fold(0, math.max);
 
     // Print out the stack trace nicely formatted.
     return frames.map((frame) {
diff --git a/pub/stack_trace/lib/src/unparsed_frame.dart b/pub/stack_trace/lib/src/unparsed_frame.dart
index 7ba9a63..78ac738 100644
--- a/pub/stack_trace/lib/src/unparsed_frame.dart
+++ b/pub/stack_trace/lib/src/unparsed_frame.dart
@@ -21,4 +21,4 @@
   UnparsedFrame(this.member);
 
   String toString() => member;
-}
\ No newline at end of file
+}
diff --git a/pub/stack_trace/pubspec.yaml b/pub/stack_trace/pubspec.yaml
index 850a701..3c25051 100644
--- a/pub/stack_trace/pubspec.yaml
+++ b/pub/stack_trace/pubspec.yaml
@@ -7,16 +7,14 @@
 #
 # When the major version is upgraded, you *must* update that version constraint
 # in pub to stay in sync with this.
-version: 1.7.3
+version: 1.7.4
 author: "Dart Team <misc@dartlang.org>"
 homepage: https://github.com/dart-lang/stack_trace
-description: >
-  A package for manipulating stack traces and printing them readably.
-
+description: A package for manipulating stack traces and printing them readably.
 dependencies:
   path: "^1.2.0"
 
 dev_dependencies:
-  test: "^0.12.0"
+  test: '^0.12.17'
 environment:
-  sdk: ">=1.14.0 <2.0.0"
+  sdk: ">=1.21.0 <2.0.0"
diff --git a/pub/test/.status b/pub/test/.status
deleted file mode 100644
index 870ef8a..0000000
--- a/pub/test/.status
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# Skip non-test files ending with "_test".
-packages/*: SkipByDesign
-*/packages/*: SkipByDesign
-*/*/packages/*: SkipByDesign
-*/*/*/packages/*: SkipByDesign
-*/*/*/*packages/*: SkipByDesign
-*/*/*/*/*packages/*: SkipByDesign
-
-# Only run tests from the test directory, since we don't care about the
-# difference between transformed an untransformed code.
-build/test/*: SkipByDesign
-build/test/*/*: SkipByDesign
-build/test/*/*/*: SkipByDesign
-build/test/*/*/*/*: SkipByDesign
-
-# Don't run library files as tests
-lib/*: SkipByDesign
-lib/*/*: SkipByDesign
-lib/*/*/*: SkipByDesign
-lib/*/*/*/*: SkipByDesign
-
-# PhantomJS isn't supported on the bots (issue 23195).
-test/runner/browser/phantom_js: Skip
-
-test/runner/browser/loader_test: Pass, Slow
-
-[ $system != windows ]
-test/runner/browser/internet_explorer: SkipByDesign
-
-[ $system != macos ]
-test/runner/browser/safari: SkipByDesign
-
-# The test harness for browser tests doesn't play nicely with the new way of
-# doing browser tests.
-[ $browser ]
-test/*: SkipByDesign
-test/*/*: SkipByDesign
-test/*/*/*: SkipByDesign
-test/*/*/*/*: SkipByDesign
diff --git a/pub/test/.test_config b/pub/test/.test_config
new file mode 100644
index 0000000..412fc5c
--- /dev/null
+++ b/pub/test/.test_config
@@ -0,0 +1,3 @@
+{
+  "test_package": true
+}
\ No newline at end of file
diff --git a/pub/test/.travis.yml b/pub/test/.travis.yml
new file mode 100644
index 0000000..2c3d05b
--- /dev/null
+++ b/pub/test/.travis.yml
@@ -0,0 +1,29 @@
+language: dart
+sudo: false
+
+dart:
+ - dev
+ - stable
+ - 1.23.0
+ - 1.22.1
+
+dart_task:
+ - test: --platform dartium
+   install_dartium: true
+ - test: --platform vm -x content-shell -x chrome -x firefox -x dartium -x phantomjs --timeout 4x
+ - dartfmt
+ - dartanalyzer
+
+matrix:
+  exclude:
+    # Repo was formatted with the 1.23 SDK.
+    - dart: 1.22.1
+      dart_task: dartfmt
+
+# Only building master means that we don't run two builds for each pull request.
+branches:
+  only: [master]
+
+cache:
+ directories:
+   - $HOME/.pub-cache
diff --git a/pub/test/BUILD.gn b/pub/test/BUILD.gn
index fcdc5ae..417807c 100644
--- a/pub/test/BUILD.gn
+++ b/pub/test/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for test-0.12.20
+# This file is generated by importer.py for test-0.12.21
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/test/CHANGELOG.md b/pub/test/CHANGELOG.md
index 7e78714..049fbfa 100644
--- a/pub/test/CHANGELOG.md
+++ b/pub/test/CHANGELOG.md
@@ -1,3 +1,68 @@
+## 0.12.21
+
+* Add a `doesNotComplete` matcher that asserts that a Future never completes.
+
+* `throwsA()` and all related matchers will now match functions that return
+  `Future`s that emit exceptions.
+
+* Respect `onPlatform` for groups.
+
+* Only print browser load errors once per browser.
+
+* Gracefully time out when attempting to deserialize a test suite.
+
+## 0.12.20+13
+
+* Upgrade to package:matcher 0.12.1
+
+## 0.12.20+12
+
+* Now support `v0.30.0` of `pkg/analyzer`
+
+* The test executable now does a "hard exit" when complete to ensure lingering
+  isolates or async code don't block completion. This may affect users trying
+  to use the Dart service protocol or observatory.
+
+## 0.12.20+11
+
+* Refactor bootstrapping to simplify the test/pub_serve transformer.
+
+## 0.12.20+10
+
+* Refactor for internal tools.
+
+## 0.12.20+9
+
+* Introduce new flag `--chain-stack-traces` to conditionally chain stack traces.
+
+## 0.12.20+8
+
+* Fixed more blockers for compiling with `dev_compiler`.
+* Dartfmt the entire repo.
+
+* **Note:** 0.12.20+5-0.12.20+7 were tagged but not officially published.
+
+## 0.12.20+4
+
+* Fixed strong-mode errors and other blockers for compiling with `dev_compiler`.
+
+## 0.12.20+3
+
+* `--pause-after-load` no longer deadlocks with recent versions of Chrome.
+
+* Fix Dartified stack traces for JS-compiled tests run through `pub serve`.
+
+## 0.12.20+2
+
+* Print "[E]" after test failures to make them easier to identify visually and
+  via automated search.
+
+## 0.12.20+1
+
+* Tighten the dependency on `stream_channel` to reflect the APIs being used.
+
+* Use a 1024 x 768 iframe for browser tests.
+
 ## 0.12.20
 
 * **Breaking change:** The `expect()` method no longer returns a `Future`, since
diff --git a/pub/test/README.md b/pub/test/README.md
index 8b34386..8cc47de 100644
--- a/pub/test/README.md
+++ b/pub/test/README.md
@@ -268,6 +268,7 @@
 Homebrew. Otherwise, you can downloaded it manually [from this
 page][content_shell]; if you do, make sure the executable named `content_shell`
 (on Mac OS or Linux) or `content_shell.exe` (on Windows) is on your system path.
+Note content_shell on linux requires the font packages ttf-kochi-mincho and ttf-kochi-gothic.
 
 [content_shell]: http://gsdview.appspot.com/dart-archive/channels/stable/release/latest/dartium/
 
diff --git a/pub/test/.analysis_options b/pub/test/analysis_options.yaml
similarity index 100%
rename from pub/test/.analysis_options
rename to pub/test/analysis_options.yaml
diff --git a/pub/test/doc/configuration.md b/pub/test/doc/configuration.md
index 4037383..ae6502b 100644
--- a/pub/test/doc/configuration.md
+++ b/pub/test/doc/configuration.md
@@ -27,6 +27,7 @@
 * [Test Configuration](#test-configuration)
   * [`timeout`](#timeout)
   * [`verbose_trace`](#verbose_trace)
+  * [`chain_stack_traces`](#chain_stack_traces)
   * [`js_trace`](#js_trace)
   * [`skip`](#skip)
   * [`test_on`](#test_on)
@@ -96,6 +97,18 @@
 verbose_trace: true
 ```
 
+### `chain_stack_traces`
+
+This boolean field controls whether or not stack traces are chained. 
+Disabling [`stack trace chaining`][stack trace chaining] will improve
+performance for heavily asynchronous code at the cost of debuggability. 
+
+[stack trace chaining]: https://github.com/dart-lang/stack_trace/blob/master/README.md#stack-chains
+
+```yaml
+chain_stack_traces: false 
+```
+
 ### `js_trace`
 
 This boolean field controls whether or not stack traces caused by errors that
diff --git a/pub/test/doc/package_config.md b/pub/test/doc/package_config.md
index 4037383..ae6502b 100644
--- a/pub/test/doc/package_config.md
+++ b/pub/test/doc/package_config.md
@@ -27,6 +27,7 @@
 * [Test Configuration](#test-configuration)
   * [`timeout`](#timeout)
   * [`verbose_trace`](#verbose_trace)
+  * [`chain_stack_traces`](#chain_stack_traces)
   * [`js_trace`](#js_trace)
   * [`skip`](#skip)
   * [`test_on`](#test_on)
@@ -96,6 +97,18 @@
 verbose_trace: true
 ```
 
+### `chain_stack_traces`
+
+This boolean field controls whether or not stack traces are chained. 
+Disabling [`stack trace chaining`][stack trace chaining] will improve
+performance for heavily asynchronous code at the cost of debuggability. 
+
+[stack trace chaining]: https://github.com/dart-lang/stack_trace/blob/master/README.md#stack-chains
+
+```yaml
+chain_stack_traces: false 
+```
+
 ### `js_trace`
 
 This boolean field controls whether or not stack traces caused by errors that
diff --git a/pub/test/lib/pub_serve.dart b/pub/test/lib/pub_serve.dart
index 8951fd4..546aef5 100644
--- a/pub/test/lib/pub_serve.dart
+++ b/pub/test/lib/pub_serve.dart
@@ -27,38 +27,29 @@
   Future apply(Transform transform) async {
     var id = transform.primaryInput.id;
 
-    transform.addOutput(
-        new Asset.fromString(id.addExtension('.vm_test.dart'), '''
+    transform.addOutput(new Asset.fromString(
+        id.addExtension('.vm_test.dart'),
+        '''
           import "dart:isolate";
 
-          import "package:stream_channel/stream_channel.dart";
-
-          import "package:test/src/runner/plugin/remote_platform_helpers.dart";
-          import "package:test/src/runner/vm/catch_isolate_errors.dart";
+          import "package:test/src/bootstrap/vm.dart";
 
           import "${p.url.basename(id.path)}" as test;
 
           void main(_, SendPort message) {
-            var channel = serializeSuite(() {
-              catchIsolateErrors();
-              return test.main;
-            });
-            new IsolateChannel.connectSend(message).pipe(channel);
+            internalBootstrapVmTest(test.main, message);
           }
         '''));
 
-    transform.addOutput(
-        new Asset.fromString(id.addExtension('.browser_test.dart'), '''
-          import "package:stream_channel/stream_channel.dart";
-
-          import "package:test/src/runner/plugin/remote_platform_helpers.dart";
-          import "package:test/src/runner/browser/post_message_channel.dart";
+    transform.addOutput(new Asset.fromString(
+        id.addExtension('.browser_test.dart'),
+        '''
+          import "package:test/src/bootstrap/browser.dart";
 
           import "${p.url.basename(id.path)}" as test;
 
           void main() {
-            var channel = serializeSuite(() => test.main);
-            postMessageChannel().pipe(channel);
+            internalBootstrapBrowserTest(test.main);
           }
         '''));
 
@@ -67,8 +58,9 @@
     var htmlId = id.changeExtension('.html');
     if (await transform.hasInput(htmlId)) return;
 
-    transform.addOutput(
-        new Asset.fromString(htmlId, '''
+    transform.addOutput(new Asset.fromString(
+        htmlId,
+        '''
           <!DOCTYPE html>
           <html>
           <head>
diff --git a/pub/test/lib/src/backend/declarer.dart b/pub/test/lib/src/backend/declarer.dart
index 7d61edf..8adeacb 100644
--- a/pub/test/lib/src/backend/declarer.dart
+++ b/pub/test/lib/src/backend/declarer.dart
@@ -96,12 +96,19 @@
   declare(body()) => runZoned(body, zoneValues: {#test.declarer: this});
 
   /// Defines a test case with the given name and body.
-  void test(String name, body(), {String testOn, Timeout timeout, skip,
-      Map<String, dynamic> onPlatform, tags}) {
+  void test(String name, body(),
+      {String testOn,
+      Timeout timeout,
+      skip,
+      Map<String, dynamic> onPlatform,
+      tags}) {
     _checkNotBuilt("test");
 
     var metadata = _metadata.merge(new Metadata.parse(
-        testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform,
+        testOn: testOn,
+        timeout: timeout,
+        skip: skip,
+        onPlatform: onPlatform,
         tags: tags));
 
     _entries.add(new LocalTest(_prefix(name), metadata, () async {
@@ -127,17 +134,24 @@
   }
 
   /// Creates a group of tests.
-  void group(String name, void body(), {String testOn, Timeout timeout, skip,
-      Map<String, dynamic> onPlatform, tags}) {
+  void group(String name, void body(),
+      {String testOn,
+      Timeout timeout,
+      skip,
+      Map<String, dynamic> onPlatform,
+      tags}) {
     _checkNotBuilt("group");
 
     var metadata = _metadata.merge(new Metadata.parse(
-        testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform,
+        testOn: testOn,
+        timeout: timeout,
+        skip: skip,
+        onPlatform: onPlatform,
         tags: tags));
     var trace = _collectTraces ? new Trace.current(2) : null;
 
-    var declarer = new Declarer._(
-        this, _prefix(name), metadata, _collectTraces, trace);
+    var declarer =
+        new Declarer._(this, _prefix(name), metadata, _collectTraces, trace);
     declarer.declare(() {
       // Cast to dynamic to avoid the analyzer complaining about us using the
       // result of a void method.
diff --git a/pub/test/lib/src/backend/group.dart b/pub/test/lib/src/backend/group.dart
index cde5aab..a8d7f71 100644
--- a/pub/test/lib/src/backend/group.dart
+++ b/pub/test/lib/src/backend/group.dart
@@ -40,14 +40,15 @@
   /// The number of tests (recursively) in this group.
   int get testCount {
     if (_testCount != null) return _testCount;
-    _testCount = entries.fold(0,
-        (count, entry) => count + (entry is Group ? entry.testCount : 1));
+    _testCount = entries.fold(
+        0, (count, entry) => count + (entry is Group ? entry.testCount : 1));
     return _testCount;
   }
+
   int _testCount;
 
-  Group(this.name, Iterable<GroupEntry> entries, {Metadata metadata,
-          this.trace, Test this.setUpAll, Test this.tearDownAll})
+  Group(this.name, Iterable<GroupEntry> entries,
+      {Metadata metadata, this.trace, this.setUpAll, this.tearDownAll})
       : entries = new List<GroupEntry>.unmodifiable(entries),
         metadata = metadata == null ? new Metadata() : metadata;
 
@@ -55,7 +56,7 @@
     if (!metadata.testOn.evaluate(platform, os: os)) return null;
     var newMetadata = metadata.forPlatform(platform, os: os);
     var filtered = _map((entry) => entry.forPlatform(platform, os: os));
-    if (filtered.isEmpty && !entries.isEmpty) return null;
+    if (filtered.isEmpty && entries.isNotEmpty) return null;
     return new Group(name, filtered,
         metadata: newMetadata,
         trace: trace,
@@ -65,7 +66,7 @@
 
   Group filter(bool callback(Test test)) {
     var filtered = _map((entry) => entry.filter(callback));
-    if (filtered.isEmpty && !entries.isEmpty) return null;
+    if (filtered.isEmpty && entries.isNotEmpty) return null;
     return new Group(name, filtered,
         metadata: metadata,
         trace: trace,
diff --git a/pub/test/lib/src/backend/invoker.dart b/pub/test/lib/src/backend/invoker.dart
index 32edf58..f7fcb48 100644
--- a/pub/test/lib/src/backend/invoker.dart
+++ b/pub/test/lib/src/backend/invoker.dart
@@ -31,8 +31,7 @@
   /// The test body.
   final AsyncFunction _body;
 
-  LocalTest(this.name, this.metadata, body(), {this.trace})
-      : _body = body;
+  LocalTest(this.name, this.metadata, body(), {this.trace}) : _body = body;
 
   /// Loads a single runnable instance of this test.
   LiveTest load(Suite suite, {Iterable<Group> groups}) {
@@ -135,7 +134,8 @@
 
   Invoker._(Suite suite, LocalTest test, {Iterable<Group> groups}) {
     _controller = new LiveTestController(
-        suite, test, _onRun, _onCloseCompleter.complete, groups: groups);
+        suite, test, _onRun, _onCloseCompleter.complete,
+        groups: groups);
   }
 
   /// Runs [callback] after this test completes.
@@ -204,9 +204,7 @@
         await fn();
         counter.removeOutstandingCallback();
       }, onError: _handleError);
-    }, zoneValues: {
-      _counterKey: counter
-    });
+    }, zoneValues: {_counterKey: counter});
 
     return counter.noOutstandingCallbacks.whenComplete(() {
       _outstandingCallbackZones.remove(zone);
@@ -221,9 +219,7 @@
   unclosable(fn()) {
     heartbeat();
 
-    return runZoned(fn, zoneValues: {
-      _closableKey: false
-    });
+    return runZoned(fn, zoneValues: {_closableKey: false});
   }
 
   /// Notifies the invoker that progress is being made.
@@ -234,15 +230,14 @@
     if (liveTest.isComplete) return;
     if (_timeoutTimer != null) _timeoutTimer.cancel();
 
-    var timeout = liveTest.test.metadata.timeout
-        .apply(new Duration(seconds: 30));
+    var timeout =
+        liveTest.test.metadata.timeout.apply(new Duration(seconds: 30));
     if (timeout == null) return;
     _timeoutTimer = _invokerZone.createTimer(timeout, () {
       _outstandingCallbackZones.last.run(() {
         if (liveTest.isComplete) return;
-        _handleError(
-            new TimeoutException(
-                "Test timed out after ${niceDuration(timeout)}.", timeout));
+        _handleError(new TimeoutException(
+            "Test timed out after ${niceDuration(timeout)}.", timeout));
       });
     });
   }
@@ -259,8 +254,8 @@
       // failing after being complete.
       _controller.setState(const State(Status.complete, Result.error));
       throw "This test was marked as skipped after it had already completed. "
-               "Make sure to use\n"
-            "[expectAsync] or the [completes] matcher when testing async code.";
+          "Make sure to use\n"
+          "[expectAsync] or the [completes] matcher when testing async code.";
     }
 
     if (message != null) _controller.message(new Message.skip(message));
@@ -294,6 +289,12 @@
     _controller.addError(error, stackTrace);
     removeAllOutstandingCallbacks();
 
+    if (!liveTest.test.metadata.chainStackTraces) {
+      _printsOnFailure.add("Consider enabling the flag chain-stack-traces to "
+          "receive more detailed exceptions.\n"
+          "For example, 'pub run test --chain-stack-traces'.");
+    }
+
     if (_printsOnFailure.isNotEmpty) {
       print(_printsOnFailure.join("\n\n"));
       _printsOnFailure.clear();
@@ -312,7 +313,7 @@
 
     _handleError(
         "This test failed after it had already completed. Make sure to use "
-            "[expectAsync]\n"
+        "[expectAsync]\n"
         "or the [completes] matcher when testing async code.",
         stackTrace);
   }
@@ -339,29 +340,29 @@
         // microtask-level events.
         new Future(() async {
           await _test._body();
-          await unclosable(() =>
-              Future.forEach(_tearDowns.reversed, errorsDontStopTest));
+          await unclosable(
+              () => Future.forEach(_tearDowns.reversed, errorsDontStopTest));
           removeOutstandingCallback();
         });
 
         await _outstandingCallbacks.noOutstandingCallbacks;
         if (_timeoutTimer != null) _timeoutTimer.cancel();
 
-        _controller.setState(
-            new State(Status.complete, liveTest.state.result));
+        _controller.setState(new State(Status.complete, liveTest.state.result));
 
         _controller.completer.complete();
-      }, zoneValues: {
-        #test.invoker: this,
-        // Use the invoker as a key so that multiple invokers can have different
-        // outstanding callback counters at once.
-        _counterKey: outstandingCallbacksForBody,
-        _closableKey: true
       },
+          zoneValues: {
+            #test.invoker: this,
+            // Use the invoker as a key so that multiple invokers can have different
+            // outstanding callback counters at once.
+            _counterKey: outstandingCallbacksForBody,
+            _closableKey: true
+          },
           zoneSpecification: new ZoneSpecification(
               print: (self, parent, zone, line) =>
                   _controller.message(new Message.print(line))),
           onError: _handleError);
-    });
+    }, when: liveTest.test.metadata.chainStackTraces);
   }
 }
diff --git a/pub/test/lib/src/backend/live_test_controller.dart b/pub/test/lib/src/backend/live_test_controller.dart
index 5e80c73..4c5cb4e 100644
--- a/pub/test/lib/src/backend/live_test_controller.dart
+++ b/pub/test/lib/src/backend/live_test_controller.dart
@@ -85,15 +85,15 @@
   ///
   /// This is synchronous to ensure that events are well-ordered across multiple
   /// streams.
-  final _onStateChangeController = new StreamController<State>
-      .broadcast(sync: true);
+  final _onStateChangeController =
+      new StreamController<State>.broadcast(sync: true);
 
   /// The controller for [LiveTest.onError].
   ///
   /// This is synchronous to ensure that events are well-ordered across multiple
   /// streams.
-  final _onErrorController = new StreamController<AsyncError>
-      .broadcast(sync: true);
+  final _onErrorController =
+      new StreamController<AsyncError>.broadcast(sync: true);
 
   /// The controller for [LiveTest.onMessage].
   ///
@@ -128,13 +128,12 @@
   /// If [groups] is passed, it's used to populate the list of groups that
   /// contain this test. Otherwise, `suite.group` is used.
   LiveTestController(Suite suite, this._test, void onRun(), void onClose(),
-          {Iterable<Group> groups})
+      {Iterable<Group> groups})
       : _suite = suite,
         _onRun = onRun,
         _onClose = onClose,
-        _groups = groups == null
-            ? [suite.group]
-            : new List.unmodifiable(groups) {
+        _groups =
+            groups == null ? [suite.group] : new List.unmodifiable(groups) {
     _liveTest = new _LiveTest(this);
   }
 
diff --git a/pub/test/lib/src/backend/message.dart b/pub/test/lib/src/backend/message.dart
index 0632fe2..6c6c4a5 100644
--- a/pub/test/lib/src/backend/message.dart
+++ b/pub/test/lib/src/backend/message.dart
@@ -30,9 +30,12 @@
 
   factory MessageType.parse(String name) {
     switch (name) {
-      case "print": return MessageType.print;
-      case "skip": return MessageType.skip;
-      default: throw new ArgumentError('Invalid message type "$name".');
+      case "print":
+        return MessageType.print;
+      case "skip":
+        return MessageType.skip;
+      default:
+        throw new ArgumentError('Invalid message type "$name".');
     }
   }
 
diff --git a/pub/test/lib/src/backend/metadata.dart b/pub/test/lib/src/backend/metadata.dart
index bdbf470..8fa6bc4 100644
--- a/pub/test/lib/src/backend/metadata.dart
+++ b/pub/test/lib/src/backend/metadata.dart
@@ -42,6 +42,10 @@
   bool get verboseTrace => _verboseTrace ?? false;
   final bool _verboseTrace;
 
+  /// Whether to chain stack traces.
+  bool get chainStackTraces => _chainStackTraces ?? true;
+  final bool _chainStackTraces;
+
   /// The user-defined tags attached to the test or suite.
   final Set<String> tags;
 
@@ -112,8 +116,8 @@
     if (tags == null) return new Set();
     if (tags is String) return new Set.from([tags]);
     if (tags is! Iterable) {
-      throw new ArgumentError.value(tags, "tags",
-          "must be either a String or an Iterable.");
+      throw new ArgumentError.value(
+          tags, "tags", "must be either a String or an Iterable.");
     }
 
     if (tags.any((tag) => tag is! String)) {
@@ -130,16 +134,23 @@
   /// If [forTag] contains metadata that applies to [tags], that metadata is
   /// included inline in the returned value. The values directly passed to the
   /// constructor take precedence over tag-specific metadata.
-  factory Metadata({PlatformSelector testOn, Timeout timeout, bool skip,
-          bool verboseTrace, String skipReason, Iterable<String> tags,
-          Map<PlatformSelector, Metadata> onPlatform,
-          Map<BooleanSelector, Metadata> forTag}) {
+  factory Metadata(
+      {PlatformSelector testOn,
+      Timeout timeout,
+      bool skip,
+      bool verboseTrace,
+      bool chainStackTraces,
+      String skipReason,
+      Iterable<String> tags,
+      Map<PlatformSelector, Metadata> onPlatform,
+      Map<BooleanSelector, Metadata> forTag}) {
     // Returns metadata without forTag resolved at all.
     _unresolved() => new Metadata._(
         testOn: testOn,
         timeout: timeout,
         skip: skip,
         verboseTrace: verboseTrace,
+        chainStackTraces: chainStackTraces,
         skipReason: skipReason,
         tags: tags,
         onPlatform: onPlatform,
@@ -167,22 +178,25 @@
   /// Creates new Metadata.
   ///
   /// Unlike [new Metadata], this assumes [forTag] is already resolved.
-  Metadata._({PlatformSelector testOn, Timeout timeout, bool skip,
-          this.skipReason, bool verboseTrace, Iterable<String> tags,
-          Map<PlatformSelector, Metadata> onPlatform,
-          Map<BooleanSelector, Metadata> forTag})
+  Metadata._(
+      {PlatformSelector testOn,
+      Timeout timeout,
+      bool skip,
+      this.skipReason,
+      bool verboseTrace,
+      bool chainStackTraces,
+      Iterable<String> tags,
+      Map<PlatformSelector, Metadata> onPlatform,
+      Map<BooleanSelector, Metadata> forTag})
       : testOn = testOn == null ? PlatformSelector.all : testOn,
         timeout = timeout == null ? const Timeout.factor(1) : timeout,
         _skip = skip,
         _verboseTrace = verboseTrace,
-        tags = new UnmodifiableSetView(
-            tags == null ? new Set() : tags.toSet()),
-        onPlatform = onPlatform == null
-            ? const {}
-            : new UnmodifiableMapView(onPlatform),
-        forTag = forTag == null
-            ? const {}
-            : new UnmodifiableMapView(forTag) {
+        _chainStackTraces = chainStackTraces,
+        tags = new UnmodifiableSetView(tags == null ? new Set() : tags.toSet()),
+        onPlatform =
+            onPlatform == null ? const {} : new UnmodifiableMapView(onPlatform),
+        forTag = forTag == null ? const {} : new UnmodifiableMapView(forTag) {
     _validateTags();
   }
 
@@ -190,15 +204,21 @@
   /// where applicable.
   ///
   /// Throws a [FormatException] if any field is invalid.
-  Metadata.parse({String testOn, Timeout timeout, skip,
-          bool verboseTrace, Map<String, dynamic> onPlatform,
-          tags})
+  Metadata.parse(
+      {String testOn,
+      Timeout timeout,
+      skip,
+      bool verboseTrace,
+      bool chainStackTraces,
+      Map<String, dynamic> onPlatform,
+      tags})
       : testOn = testOn == null
             ? PlatformSelector.all
             : new PlatformSelector.parse(testOn),
         timeout = timeout == null ? const Timeout.factor(1) : timeout,
         _skip = skip == null ? null : skip != false,
         _verboseTrace = verboseTrace,
+        _chainStackTraces = chainStackTraces,
         skipReason = skip is String ? skip : null,
         onPlatform = _parseOnPlatform(onPlatform),
         tags = _parseTags(tags),
@@ -220,6 +240,7 @@
         _skip = serialized['skip'],
         skipReason = serialized['skipReason'],
         _verboseTrace = serialized['verboseTrace'],
+        _chainStackTraces = serialized['chainStackTraces'],
         tags = new Set.from(serialized['tags']),
         onPlatform = new Map.fromIterable(serialized['onPlatform'],
             key: (pair) => new PlatformSelector.parse(pair.first),
@@ -233,8 +254,7 @@
     if (serialized == 'none') return Timeout.none;
     var scaleFactor = serialized['scaleFactor'];
     if (scaleFactor != null) return new Timeout.factor(scaleFactor);
-    return new Timeout(
-        new Duration(microseconds: serialized['duration']));
+    return new Timeout(new Duration(microseconds: serialized['duration']));
   }
 
   /// Throws an [ArgumentError] if any tags in [tags] aren't hyphenated
@@ -247,10 +267,9 @@
 
     if (invalidTags.isEmpty) return;
 
-    throw new ArgumentError(
-        "Invalid ${pluralize('tag', invalidTags.length)} "
-          "${toSentence(invalidTags)}. Tags must be (optionally hyphenated) "
-          "Dart identifiers.");
+    throw new ArgumentError("Invalid ${pluralize('tag', invalidTags.length)} "
+        "${toSentence(invalidTags)}. Tags must be (optionally hyphenated) "
+        "Dart identifiers.");
   }
 
   /// Return a new [Metadata] that merges [this] with [other].
@@ -258,18 +277,18 @@
   /// If the two [Metadata]s have conflicting properties, [other] wins. If
   /// either has a [forTag] metadata for one of the other's tags, that metadata
   /// is merged as well.
-  Metadata merge(Metadata other) =>
-      new Metadata(
-          testOn: testOn.intersection(other.testOn),
-          timeout: timeout.merge(other.timeout),
-          skip: other._skip ?? _skip,
-          skipReason: other.skipReason ?? skipReason,
-          verboseTrace: other._verboseTrace ?? _verboseTrace,
-          tags: tags.union(other.tags),
-          onPlatform: mergeMaps(onPlatform, other.onPlatform,
-              value: (metadata1, metadata2) => metadata1.merge(metadata2)),
-          forTag: mergeMaps(forTag, other.forTag,
-              value: (metadata1, metadata2) => metadata1.merge(metadata2)));
+  Metadata merge(Metadata other) => new Metadata(
+      testOn: testOn.intersection(other.testOn),
+      timeout: timeout.merge(other.timeout),
+      skip: other._skip ?? _skip,
+      skipReason: other.skipReason ?? skipReason,
+      verboseTrace: other._verboseTrace ?? _verboseTrace,
+      chainStackTraces: other._chainStackTraces ?? _chainStackTraces,
+      tags: tags.union(other.tags),
+      onPlatform: mergeMaps(onPlatform, other.onPlatform,
+          value: (metadata1, metadata2) => metadata1.merge(metadata2)),
+      forTag: mergeMaps(forTag, other.forTag,
+          value: (metadata1, metadata2) => metadata1.merge(metadata2)));
 
   /// Returns a copy of [this] with the given fields changed.
   Metadata change(
@@ -277,6 +296,7 @@
       Timeout timeout,
       bool skip,
       bool verboseTrace,
+      bool chainStackTraces,
       String skipReason,
       Map<PlatformSelector, Metadata> onPlatform,
       Set<String> tags,
@@ -285,13 +305,21 @@
     timeout ??= this.timeout;
     skip ??= this._skip;
     verboseTrace ??= this._verboseTrace;
+    chainStackTraces ??= this._chainStackTraces;
     skipReason ??= this.skipReason;
     onPlatform ??= this.onPlatform;
     tags ??= this.tags;
     forTag ??= this.forTag;
-    return new Metadata(testOn: testOn, timeout: timeout, skip: skip,
-        verboseTrace: verboseTrace, skipReason: skipReason,
-        onPlatform: onPlatform, tags: tags, forTag: forTag);
+    return new Metadata(
+        testOn: testOn,
+        timeout: timeout,
+        skip: skip,
+        verboseTrace: verboseTrace,
+        chainStackTraces: chainStackTraces,
+        skipReason: skipReason,
+        onPlatform: onPlatform,
+        tags: tags,
+        forTag: forTag);
   }
 
   /// Returns a copy of [this] with all platform-specific metadata from
@@ -322,6 +350,7 @@
       'skip': _skip,
       'skipReason': skipReason,
       'verboseTrace': _verboseTrace,
+      'chainStackTraces': _chainStackTraces,
       'tags': tags.toList(),
       'onPlatform': serializedOnPlatform,
       'forTag': mapMap(forTag,
@@ -334,9 +363,8 @@
   _serializeTimeout(Timeout timeout) {
     if (timeout == Timeout.none) return 'none';
     return {
-      'duration': timeout.duration == null
-          ? null
-          : timeout.duration.inMicroseconds,
+      'duration':
+          timeout.duration == null ? null : timeout.duration.inMicroseconds,
       'scaleFactor': timeout.scaleFactor
     };
   }
diff --git a/pub/test/lib/src/backend/operating_system.dart b/pub/test/lib/src/backend/operating_system.dart
index 516d020..474f10f 100644
--- a/pub/test/lib/src/backend/operating_system.dart
+++ b/pub/test/lib/src/backend/operating_system.dart
@@ -43,7 +43,7 @@
   /// If no operating system is found, returns [none].
   static OperatingSystem find(String identifier) =>
       all.firstWhere((platform) => platform.identifier == identifier,
-      orElse: () => null);
+          orElse: () => null);
 
   /// Finds an operating system by the return value from `dart:io`'s
   /// `Platform.operatingSystem`.
@@ -51,12 +51,18 @@
   /// If no operating system is found, returns [none].
   static OperatingSystem findByIoName(String name) {
     switch (name) {
-      case "windows": return windows;
-      case "macos": return macOS;
-      case "linux": return linux;
-      case "android": return android;
-      case "ios": return iOS;
-      default: return none;
+      case "windows":
+        return windows;
+      case "macos":
+        return macOS;
+      case "linux":
+        return linux;
+      case "android":
+        return android;
+      case "ios":
+        return iOS;
+      default:
+        return none;
     }
   }
 
diff --git a/pub/test/lib/src/backend/platform_selector.dart b/pub/test/lib/src/backend/platform_selector.dart
index 10969f7..590fc4e 100644
--- a/pub/test/lib/src/backend/platform_selector.dart
+++ b/pub/test/lib/src/backend/platform_selector.dart
@@ -11,8 +11,8 @@
 /// The set of all valid variable names.
 final _validVariables =
     new Set<String>.from(["posix", "dart-vm", "browser", "js", "blink"])
-        ..addAll(TestPlatform.all.map((platform) => platform.identifier))
-        ..addAll(OperatingSystem.all.map((os) => os.identifier));
+      ..addAll(TestPlatform.all.map((platform) => platform.identifier))
+      ..addAll(OperatingSystem.all.map((os) => os.identifier));
 
 /// An expression for selecting certain platforms, including operating systems
 /// and browsers.
@@ -48,12 +48,18 @@
       if (variable == platform.identifier) return true;
       if (variable == os.identifier) return true;
       switch (variable) {
-        case "dart-vm": return platform.isDartVM;
-        case "browser": return platform.isBrowser;
-        case "js": return platform.isJS;
-        case "blink": return platform.isBlink;
-        case "posix": return os.isPosix;
-        default: return false;
+        case "dart-vm":
+          return platform.isDartVM;
+        case "browser":
+          return platform.isBrowser;
+        case "js":
+          return platform.isJS;
+        case "blink":
+          return platform.isBlink;
+        case "posix":
+          return os.isPosix;
+        default:
+          return false;
       }
     });
   }
@@ -67,7 +73,8 @@
 
   String toString() => _inner.toString();
 
-  bool operator==(other) => other is PlatformSelector && _inner == other._inner;
+  bool operator ==(other) =>
+      other is PlatformSelector && _inner == other._inner;
 
   int get hashCode => _inner.hashCode;
 }
diff --git a/pub/test/lib/src/backend/state.dart b/pub/test/lib/src/backend/state.dart
index f846d69..fe6d76d 100644
--- a/pub/test/lib/src/backend/state.dart
+++ b/pub/test/lib/src/backend/state.dart
@@ -27,8 +27,8 @@
 
   const State(this.status, this.result);
 
-  bool operator==(other) => other is State && status == other.status &&
-      result == other.result;
+  bool operator ==(other) =>
+      other is State && status == other.status && result == other.result;
 
   int get hashCode => status.hashCode ^ (7 * result.hashCode);
 
@@ -62,9 +62,12 @@
 
   factory Status.parse(String name) {
     switch (name) {
-      case "pending": return Status.pending;
-      case "running": return Status.running;
-      case "complete": return Status.complete;
+      case "pending":
+        return Status.pending;
+      case "running":
+        return Status.running;
+      case "complete":
+        return Status.complete;
       default:
         throw new ArgumentError('Invalid status name "$name".');
     }
@@ -116,10 +119,14 @@
 
   factory Result.parse(String name) {
     switch (name) {
-      case "success": return Result.success;
-      case "skipped": return Result.skipped;
-      case "failure": return Result.failure;
-      case "error": return Result.error;
+      case "success":
+        return Result.success;
+      case "skipped":
+        return Result.skipped;
+      case "failure":
+        return Result.failure;
+      case "error":
+        return Result.error;
       default:
         throw new ArgumentError('Invalid result name "$name".');
     }
diff --git a/pub/test/lib/src/backend/suite.dart b/pub/test/lib/src/backend/suite.dart
index 49d77e8..2846993 100644
--- a/pub/test/lib/src/backend/suite.dart
+++ b/pub/test/lib/src/backend/suite.dart
@@ -48,11 +48,11 @@
   /// Returns [entries] filtered according to [platform] and [os].
   ///
   /// Gracefully handles [platform] being null.
-  static Group _filterGroup(Group group, TestPlatform platform,
-      OperatingSystem os) {
+  static Group _filterGroup(
+      Group group, TestPlatform platform, OperatingSystem os) {
     if (platform == null && os != null) {
-      throw new ArgumentError.value(null, "os",
-          "If os is passed, platform must be passed as well");
+      throw new ArgumentError.value(
+          null, "os", "If os is passed, platform must be passed as well");
     }
 
     if (platform == null) return group;
diff --git a/pub/test/lib/src/backend/test_platform.dart b/pub/test/lib/src/backend/test_platform.dart
index 0af1a66..dc21389 100644
--- a/pub/test/lib/src/backend/test_platform.dart
+++ b/pub/test/lib/src/backend/test_platform.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:collection';
+
 // TODO(nweiz): support pluggable platforms.
 /// An enum of all platforms on which tests can run.
 class TestPlatform {
@@ -31,12 +33,12 @@
       isBrowser: true, isJS: true, isBlink: true, isHeadless: true);
 
   /// Mozilla Firefox.
-  static const TestPlatform firefox = const TestPlatform._("Firefox", "firefox",
-      isBrowser: true, isJS: true);
+  static const TestPlatform firefox =
+      const TestPlatform._("Firefox", "firefox", isBrowser: true, isJS: true);
 
   /// Apple Safari.
-  static const TestPlatform safari = const TestPlatform._("Safari", "safari",
-      isBrowser: true, isJS: true);
+  static const TestPlatform safari =
+      const TestPlatform._("Safari", "safari", isBrowser: true, isJS: true);
 
   /// Microsoft Internet Explorer.
   static const TestPlatform internetExplorer = const TestPlatform._(
@@ -44,16 +46,8 @@
       isBrowser: true, isJS: true);
 
   /// A list of all instances of [TestPlatform].
-  static const List<TestPlatform> all = const [
-    vm,
-    dartium,
-    contentShell,
-    chrome,
-    phantomJS,
-    firefox,
-    safari,
-    internetExplorer
-  ];
+  static final UnmodifiableListView<TestPlatform> all =
+      new UnmodifiableListView<TestPlatform>(_allPlatforms);
 
   /// Finds a platform by its identifier string.
   ///
@@ -83,9 +77,44 @@
   /// Whether this platform has no visible window.
   final bool isHeadless;
 
-  const TestPlatform._(this.name, this.identifier, {this.isDartVM: false,
-      this.isBrowser: false, this.isJS: false, this.isBlink: false,
+  const TestPlatform._(this.name, this.identifier,
+      {this.isDartVM: false,
+      this.isBrowser: false,
+      this.isJS: false,
+      this.isBlink: false,
       this.isHeadless: false});
 
   String toString() => name;
 }
+
+final List<TestPlatform> _allPlatforms = [
+  TestPlatform.vm,
+  TestPlatform.dartium,
+  TestPlatform.contentShell,
+  TestPlatform.chrome,
+  TestPlatform.phantomJS,
+  TestPlatform.firefox,
+  TestPlatform.safari,
+  TestPlatform.internetExplorer
+];
+
+/// **Do not call this function without express permission from the test package
+/// authors**.
+///
+/// This constructs and globally registers a new TestPlatform with the provided
+/// details.
+TestPlatform registerTestPlatform(String name, String identifier,
+    {bool isDartVM: false,
+    bool isBrowser: false,
+    bool isJS: false,
+    bool isBlink: false,
+    bool isHeadless: false}) {
+  var platform = new TestPlatform._(name, identifier,
+      isDartVM: isDartVM,
+      isBrowser: isBrowser,
+      isJS: isJS,
+      isBlink: isBlink,
+      isHeadless: isHeadless);
+  _allPlatforms.add(platform);
+  return platform;
+}
diff --git a/pub/test/lib/src/bootstrap/browser.dart b/pub/test/lib/src/bootstrap/browser.dart
new file mode 100644
index 0000000..c061711
--- /dev/null
+++ b/pub/test/lib/src/bootstrap/browser.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import "../runner/browser/post_message_channel.dart";
+import "../runner/plugin/remote_platform_helpers.dart";
+import "../utils.dart";
+
+/// Bootstraps a browser test to communicate with the test runner.
+///
+/// This should NOT be used directly, instead use the `test/pub_serve`
+/// transformer which will bootstrap your test and call this method.
+void internalBootstrapBrowserTest(AsyncFunction originalMain) {
+  var channel = serializeSuite(() => originalMain);
+  postMessageChannel().pipe(channel);
+}
diff --git a/pub/test/lib/src/bootstrap/vm.dart b/pub/test/lib/src/bootstrap/vm.dart
new file mode 100644
index 0000000..c6cd010
--- /dev/null
+++ b/pub/test/lib/src/bootstrap/vm.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import "dart:isolate";
+
+import "package:stream_channel/stream_channel.dart";
+
+import "../runner/plugin/remote_platform_helpers.dart";
+import "../runner/vm/catch_isolate_errors.dart";
+import "../utils.dart";
+
+/// Bootstraps a vm test to communicate with the test runner.
+///
+/// This should NOT be used directly, instead use the `test/pub_serve`
+/// transformer which will bootstrap your test and call this method.
+void internalBootstrapVmTest(AsyncFunction originalMain, SendPort sendPort) {
+  var channel = serializeSuite(() {
+    catchIsolateErrors();
+    return originalMain;
+  });
+  new IsolateChannel.connectSend(sendPort).pipe(channel);
+}
diff --git a/pub/test/lib/src/executable.dart b/pub/test/lib/src/executable.dart
index 20f4cdb..8293985 100644
--- a/pub/test/lib/src/executable.dart
+++ b/pub/test/lib/src/executable.dart
@@ -29,10 +29,8 @@
 /// terminates the program immediately.
 final _signals = Platform.isWindows
     ? ProcessSignal.SIGINT.watch()
-    : StreamGroup.merge([
-        ProcessSignal.SIGTERM.watch(),
-        ProcessSignal.SIGINT.watch()
-      ]);
+    : StreamGroup
+        .merge([ProcessSignal.SIGTERM.watch(), ProcessSignal.SIGINT.watch()]);
 
 /// Returns whether the current package has a pubspec which uses the
 /// `test/pub_serve` transformer.
@@ -62,7 +60,7 @@
 }
 
 /// Returns the path to the global test configuration file.
-final String _globalConfigPath = (){
+final String _globalConfigPath = () {
   if (Platform.environment.containsKey('DART_TEST_CONFIG')) {
     return Platform.environment['DART_TEST_CONFIG'];
   } else if (Platform.operatingSystem == 'windows') {
@@ -101,13 +99,13 @@
   try {
     var fileConfiguration = Configuration.empty;
     if (new File(_globalConfigPath).existsSync()) {
-      fileConfiguration = fileConfiguration.merge(
-          new Configuration.load(_globalConfigPath, global: true));
+      fileConfiguration = fileConfiguration
+          .merge(new Configuration.load(_globalConfigPath, global: true));
     }
 
     if (new File(configuration.configurationPath).existsSync()) {
-      fileConfiguration = fileConfiguration.merge(
-          new Configuration.load(configuration.configurationPath));
+      fileConfiguration = fileConfiguration
+          .merge(new Configuration.load(configuration.configurationPath));
     }
 
     configuration = fileConfiguration.merge(configuration);
@@ -125,10 +123,9 @@
     return;
   }
 
-  var undefinedPresets =
-      configuration.chosenPresets
-          .where((preset) => !configuration.knownPresets.contains(preset))
-          .toList();
+  var undefinedPresets = configuration.chosenPresets
+      .where((preset) => !configuration.knownPresets.contains(preset))
+      .toList();
   if (undefinedPresets.isNotEmpty) {
     _printUsage("Undefined ${pluralize('preset', undefinedPresets.length)} "
         "${toSentence(undefinedPresets.map((preset) => '"$preset"'))}.");
@@ -178,14 +175,19 @@
   } catch (error, stackTrace) {
     stderr.writeln(getErrorMessage(error));
     stderr.writeln(new Trace.from(stackTrace).terse);
-    stderr.writeln(
-        "This is an unexpected error. Please file an issue at "
-            "http://github.com/dart-lang/test\n"
+    stderr.writeln("This is an unexpected error. Please file an issue at "
+        "http://github.com/dart-lang/test\n"
         "with the stack trace and instructions for reproducing the error.");
     exitCode = exit_codes.software;
   } finally {
     await close();
   }
+
+  // TODO(grouma) - figure out why the executable can hang in the travis
+  // environment. https://github.com/dart-lang/test/issues/599
+  if (Platform.environment["TRAVIS"] == "true") {
+    exit(exitCode);
+  }
 }
 
 /// Print usage information for this command.
diff --git a/pub/test/lib/src/frontend/async_matcher.dart b/pub/test/lib/src/frontend/async_matcher.dart
index b7741f1..df4157a 100644
--- a/pub/test/lib/src/frontend/async_matcher.dart
+++ b/pub/test/lib/src/frontend/async_matcher.dart
@@ -31,11 +31,14 @@
 
   bool matches(item, Map matchState) {
     var result = matchAsync(item);
-    expect(result, anyOf([
-      equals(null),
-      new isInstanceOf<Future>(),
-      new isInstanceOf<String>()
-    ]), reason: "matchAsync() may only return a String, a Future, or null.");
+    expect(
+        result,
+        anyOf([
+          equals(null),
+          new isInstanceOf<Future>(),
+          new isInstanceOf<String>()
+        ]),
+        reason: "matchAsync() may only return a String, a Future, or null.");
 
     if (result is Future) {
       Invoker.current.addOutstandingCallback();
diff --git a/pub/test/lib/src/frontend/expect.dart b/pub/test/lib/src/frontend/expect.dart
index 6e25f7a..4272b69 100644
--- a/pub/test/lib/src/frontend/expect.dart
+++ b/pub/test/lib/src/frontend/expect.dart
@@ -85,10 +85,7 @@
 
 /// The implementation of [expect] and [expectLater].
 Future _expect(actual, matcher,
-    {String reason,
-    skip,
-    bool verbose: false,
-    ErrorFormatter formatter}) {
+    {String reason, skip, bool verbose: false, ErrorFormatter formatter}) {
   formatter ??= (actual, matcher, reason, matchState, verbose) {
     var mismatchDescription = new StringDescription();
     matcher.describeMismatch(actual, mismatchDescription, matchState, verbose);
@@ -126,11 +123,14 @@
   if (matcher is AsyncMatcher) {
     // Avoid async/await so that expect() throws synchronously when possible.
     var result = matcher.matchAsync(actual);
-    expect(result, anyOf([
-      equals(null),
-      new isInstanceOf<Future>(),
-      new isInstanceOf<String>()
-    ]), reason: "matchAsync() may only return a String, a Future, or null.");
+    expect(
+        result,
+        anyOf([
+          equals(null),
+          new isInstanceOf<Future>(),
+          new isInstanceOf<String>()
+        ]),
+        reason: "matchAsync() may only return a String, a Future, or null.");
 
     if (result is String) {
       fail(formatFailure(matcher, actual, result, reason: reason));
@@ -167,8 +167,8 @@
 @Deprecated("Will be removed in 0.13.0.")
 String formatFailure(Matcher expected, actual, String which, {String reason}) {
   var buffer = new StringBuffer();
-  buffer.writeln(indent(prettyPrint(expected),       first: 'Expected: '));
-  buffer.writeln(indent(prettyPrint(actual),         first: '  Actual: '));
+  buffer.writeln(indent(prettyPrint(expected), first: 'Expected: '));
+  buffer.writeln(indent(prettyPrint(actual), first: '  Actual: '));
   if (which.isNotEmpty) buffer.writeln(indent(which, first: '   Which: '));
   if (reason != null) buffer.writeln(reason);
   return buffer.toString();
diff --git a/pub/test/lib/src/frontend/expect_async.dart b/pub/test/lib/src/frontend/expect_async.dart
index af0f16b..2868144 100644
--- a/pub/test/lib/src/frontend/expect_async.dart
+++ b/pub/test/lib/src/frontend/expect_async.dart
@@ -96,9 +96,8 @@
       {String id, String reason, bool isDone()})
       : this._callback = callback,
         _minExpectedCalls = minExpected,
-        _maxExpectedCalls = (maxExpected == 0 && minExpected > 0)
-            ? minExpected
-            : maxExpected,
+        _maxExpectedCalls =
+            (maxExpected == 0 && minExpected > 0) ? minExpected : maxExpected,
         this._isDone = isDone,
         this._reason = reason == null ? '' : '\n$reason',
         this._zone = Zone.current,
@@ -446,8 +445,8 @@
 /// This method takes callbacks with five arguments. See also
 /// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
 /// [expectAsync4], and [expectAsync6] for callbacks with different arity.
-Func5<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/,
-        dynamic/*=D*/, dynamic/*=E*/ >
+Func5<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, dynamic/*=D*/,
+        dynamic/*=E*/ >
     expectAsync5/*<T, A, B, C, D, E>*/(
         dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b,
             dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e),
@@ -485,8 +484,8 @@
 /// This method takes callbacks with six arguments. See also
 /// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
 /// [expectAsync4], and [expectAsync5] for callbacks with different arity.
-Func6<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/,
-        dynamic/*=D*/, dynamic/*=E*/, dynamic/*=F*/ >
+Func6<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, dynamic/*=D*/,
+        dynamic/*=E*/, dynamic/*=F*/ >
     expectAsync6/*<T, A, B, C, D, E, F>*/(
         dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b,
             dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e, dynamic/*=F*/ f),
@@ -697,8 +696,8 @@
 /// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil2],
 /// [expectAsyncUntil3], [expectAsyncUntil4], and [expectAsyncUntil6] for
 /// callbacks with different arity.
-Func5<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/,
-        dynamic/*=D*/, dynamic/*=E*/ >
+Func5<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, dynamic/*=D*/,
+        dynamic/*=E*/ >
     expectAsyncUntil5/*<T, A, B, C, D, E>*/(
         dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b,
             dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e),
@@ -732,8 +731,8 @@
 /// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil2],
 /// [expectAsyncUntil3], [expectAsyncUntil4], and [expectAsyncUntil5] for
 /// callbacks with different arity.
-Func6<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/,
-        dynamic/*=D*/, dynamic/*=E*/, dynamic/*=F*/ >
+Func6<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, dynamic/*=D*/,
+        dynamic/*=E*/, dynamic/*=F*/ >
     expectAsyncUntil6/*<T, A, B, C, D, E, F>*/(
         dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b,
             dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e, dynamic/*=F*/ f),
diff --git a/pub/test/lib/src/frontend/future_matchers.dart b/pub/test/lib/src/frontend/future_matchers.dart
index a3001a3..0284a4d 100644
--- a/pub/test/lib/src/frontend/future_matchers.dart
+++ b/pub/test/lib/src/frontend/future_matchers.dart
@@ -65,7 +65,7 @@
       }
 
       var buffer = new StringBuffer();
-      buffer.writeln(indent(prettyPrint(value),            first: 'emitted '));
+      buffer.writeln(indent(prettyPrint(value), first: 'emitted '));
       if (result.isNotEmpty) buffer.writeln(indent(result, first: '  which '));
       return buffer.toString().trimRight();
     });
@@ -80,3 +80,43 @@
     return description;
   }
 }
+
+/// Matches a [Future] that does not complete.
+///
+/// Note that this creates an asynchronous expectation. The call to
+/// `expect()` that includes this will return immediately and execution will
+/// continue.
+final Matcher doesNotComplete = const _DoesNotComplete(20);
+
+class _DoesNotComplete extends Matcher {
+  final int _timesToPump;
+  const _DoesNotComplete(this._timesToPump);
+
+  // TODO(grouma) - Make this a top level function
+  Future _pumpEventQueue(times) {
+    if (times == 0) return new Future.value();
+    return new Future(() => _pumpEventQueue(times - 1));
+  }
+
+  Description describe(Description description) {
+    description.add("does not complete");
+    return description;
+  }
+
+  @override
+  bool matches(item, Map matchState) {
+    if (item is! Future) return false;
+    item.then((value) {
+      fail('Future was not expected to complete but completed with a value of '
+          '$value');
+    });
+    expect(_pumpEventQueue(_timesToPump), completes);
+    return true;
+  }
+
+  Description describeMismatch(
+      item, Description description, Map matchState, bool verbose) {
+    if (item is! Future) return description.add("$item is not a Future");
+    return description;
+  }
+}
diff --git a/pub/test/lib/src/frontend/prints_matcher.dart b/pub/test/lib/src/frontend/prints_matcher.dart
index faefd97..421425f 100644
--- a/pub/test/lib/src/frontend/prints_matcher.dart
+++ b/pub/test/lib/src/frontend/prints_matcher.dart
@@ -61,7 +61,7 @@
     if (actual.isEmpty) {
       buffer.writeln('printed nothing');
     } else {
-      buffer.writeln(indent(prettyPrint(actual),         first: 'printed '));
+      buffer.writeln(indent(prettyPrint(actual), first: 'printed '));
     }
     if (result.isNotEmpty) buffer.writeln(indent(result, first: '  which '));
     return buffer.toString().trimRight();
diff --git a/pub/test/lib/src/frontend/spawn_hybrid.dart b/pub/test/lib/src/frontend/spawn_hybrid.dart
index 8c9b85d..37f9517 100644
--- a/pub/test/lib/src/frontend/spawn_hybrid.dart
+++ b/pub/test/lib/src/frontend/spawn_hybrid.dart
@@ -22,26 +22,26 @@
 /// messages are printed using `print()`.
 final _transformer = new StreamChannelTransformer<Object, Map>(
     new StreamTransformer.fromHandlers(handleData: (message, sink) {
-      switch (message["type"]) {
-        case "data":
-          sink.add(message["data"]);
-          break;
+  switch (message["type"]) {
+    case "data":
+      sink.add(message["data"]);
+      break;
 
-        case "print":
-          print(message["line"]);
-          break;
+    case "print":
+      print(message["line"]);
+      break;
 
-        case "error":
-          var error = RemoteException.deserialize(message["error"]);
-          sink.addError(error.error, error.stackTrace);
-          break;
-      }
-    }), new StreamSinkTransformer.fromHandlers(handleData: (message, sink) {
-      // This is called synchronously from the user's `Sink.add()` call, so if
-      // [ensureJsonEncodable] throws here they'll get a helpful stack trace.
-      ensureJsonEncodable(message);
-      sink.add(message);
-    }));
+    case "error":
+      var error = RemoteException.deserialize(message["error"]);
+      sink.addError(error.error, error.stackTrace);
+      break;
+  }
+}), new StreamSinkTransformer.fromHandlers(handleData: (message, sink) {
+  // This is called synchronously from the user's `Sink.add()` call, so if
+  // [ensureJsonEncodable] throws here they'll get a helpful stack trace.
+  ensureJsonEncodable(message);
+  sink.add(message);
+}));
 
 /// Spawns a VM isolate for the given [uri], which may be a [Uri] or a [String].
 ///
@@ -149,8 +149,8 @@
 ///
 /// **Note**: If you use this API, be sure to add a dependency on the
 /// **`stream_channel` package, since you're using its API as well!
-StreamChannel spawnHybridCode(String dartCode, {Object message,
-    bool stayAlive: false}) {
+StreamChannel spawnHybridCode(String dartCode,
+    {Object message, bool stayAlive: false}) {
   var uri = new Uri.dataFromString(dartCode,
       encoding: UTF8, mimeType: 'application/dart');
   return _spawn(uri.toString(), message, stayAlive: stayAlive);
@@ -163,8 +163,7 @@
   if (channel == null) {
     // TODO(nweiz): Link to an issue tracking support when running the test file
     // directly.
-    throw new UnsupportedError(
-        "Can't connect to the test runner.\n"
+    throw new UnsupportedError("Can't connect to the test runner.\n"
         'spawnHybridUri() is currently only supported within "pub run test".');
   }
 
diff --git a/pub/test/lib/src/frontend/stream_matcher.dart b/pub/test/lib/src/frontend/stream_matcher.dart
index 139b094..6c90674 100644
--- a/pub/test/lib/src/frontend/stream_matcher.dart
+++ b/pub/test/lib/src/frontend/stream_matcher.dart
@@ -87,9 +87,8 @@
   /// should be grammatically valid when used after the word "should". For
   /// example, it might be "emit the right events".
   factory StreamMatcher(
-          Future<String> matchQueue(StreamQueue queue),
-          String description)
-      = _StreamMatcher;
+          Future<String> matchQueue(StreamQueue queue), String description) =
+      _StreamMatcher;
 
   /// Tries to match events emitted by [queue].
   ///
@@ -150,7 +149,8 @@
       // of the error message.
       var replay = transaction.newQueue();
       var events = <Result>[];
-      var subscription = Result.captureStreamTransformer.bind(replay.rest)
+      var subscription = Result.captureStreamTransformer
+          .bind(replay.rest)
           .listen(events.add, onDone: () => events.add(null));
 
       // Wait on a timer tick so all buffered events are emitted.
@@ -173,7 +173,7 @@
       transaction.reject();
 
       var buffer = new StringBuffer();
-      buffer.writeln(indent(eventsString,                  first: "emitted "));
+      buffer.writeln(indent(eventsString, first: "emitted "));
       if (result.isNotEmpty) buffer.writeln(indent(result, first: "  which "));
       return buffer.toString().trimRight();
     }, onError: (error) {
diff --git a/pub/test/lib/src/frontend/stream_matchers.dart b/pub/test/lib/src/frontend/stream_matchers.dart
index 84d0cdd..cc6a3aa 100644
--- a/pub/test/lib/src/frontend/stream_matchers.dart
+++ b/pub/test/lib/src/frontend/stream_matchers.dart
@@ -7,15 +7,14 @@
 import 'package:async/async.dart';
 import 'package:matcher/matcher.dart';
 
+import '../utils.dart';
 import 'async_matcher.dart';
 import 'stream_matcher.dart';
 import 'throws_matcher.dart';
-import '../utils.dart';
 
 /// Returns a [StreamMatcher] that asserts that the stream emits a "done" event.
 final emitsDone = new StreamMatcher(
-    (queue) async => (await queue.hasNext) ? "" : null,
-    "be done");
+    (queue) async => (await queue.hasNext) ? "" : null, "be done");
 
 /// Returns a [StreamMatcher] for [matcher].
 ///
@@ -70,13 +69,13 @@
 StreamMatcher mayEmit(matcher) {
   var streamMatcher = emits(matcher);
   return new StreamMatcher((queue) async {
-    await queue.withTransaction((copy) async =>
-        (await streamMatcher.matchQueue(copy)) == null);
+    await queue.withTransaction(
+        (copy) async => (await streamMatcher.matchQueue(copy)) == null);
     return null;
   }, "maybe ${streamMatcher.description}");
 }
 
-/// Returns a [streamMatcher] that matches the stream if at least one of
+/// Returns a [StreamMatcher] that matches the stream if at least one of
 /// [matchers] matches.
 ///
 /// If multiple matchers match the stream, this chooses the matcher that
@@ -169,8 +168,8 @@
   var streamMatchers = matchers.map(emits).toList();
   if (streamMatchers.length == 1) return streamMatchers.first;
 
-  var description = "do the following in order:\n" + bullet(
-      streamMatchers.map((matcher) => matcher.description));
+  var description = "do the following in order:\n" +
+      bullet(streamMatchers.map((matcher) => matcher.description));
 
   return new StreamMatcher((queue) async {
     for (var i = 0; i < streamMatchers.length; i++) {
@@ -200,11 +199,11 @@
     var failures = <String>[];
 
     tryHere() => queue.withTransaction((copy) async {
-      var result = await streamMatcher.matchQueue(copy);
-      if (result == null) return true;
-      failures.add(result);
-      return false;
-    });
+          var result = await streamMatcher.matchQueue(copy);
+          if (result == null) return true;
+          failures.add(result);
+          return false;
+        });
 
     while (await queue.hasNext) {
       if (await tryHere()) return null;
@@ -313,18 +312,18 @@
   var streamMatchers = matchers.map(emits).toSet();
   if (streamMatchers.length == 1) return streamMatchers.first;
   var description = "do the following in any order:\n" +
-    bullet(streamMatchers.map((matcher) => matcher.description));
+      bullet(streamMatchers.map((matcher) => matcher.description));
 
   return new StreamMatcher(
-      (queue) async =>
-          await _tryInAnyOrder(queue, streamMatchers) ? null : "",
+      (queue) async => await _tryInAnyOrder(queue, streamMatchers) ? null : "",
       description);
 }
 
 /// Returns whether [queue] matches [matchers] in any order.
-Future<bool> _tryInAnyOrder(StreamQueue queue, Set<StreamMatcher> matchers)
-    async {
-  if (matchers.length == 1) return await matchers.first.matchQueue(queue) == null;
+Future<bool> _tryInAnyOrder(
+    StreamQueue queue, Set<StreamMatcher> matchers) async {
+  if (matchers.length == 1)
+    return await matchers.first.matchQueue(queue) == null;
 
   var transaction = queue.startTransaction();
   StreamQueue consumedMost;
diff --git a/pub/test/lib/src/frontend/throws_matcher.dart b/pub/test/lib/src/frontend/throws_matcher.dart
index 90b27aa..8518c0f 100644
--- a/pub/test/lib/src/frontend/throws_matcher.dart
+++ b/pub/test/lib/src/frontend/throws_matcher.dart
@@ -17,7 +17,7 @@
 @Deprecated("Will be removed in 0.13.0")
 const Matcher throws = const Throws();
 
-/// This can be used to match two kinds of objects:
+/// This can be used to match three kinds of objects:
 ///
 /// * A [Function] that throws an exception when called. The function cannot
 ///   take any arguments. If you want to test that a function expecting
@@ -29,7 +29,9 @@
 ///   return immediately and execution will continue. Later, when the future
 ///   completes, the actual expectation will run.
 ///
-/// In both cases, when an exception is thrown, this will test that the
+/// * A [Function] that returns a [Future] that completes with an exception.
+///
+/// In all three cases, when an exception is thrown, this will test that the
 /// exception object matches [matcher]. If [matcher] is not an instance of
 /// [Matcher], it will implicitly be treated as `equals(matcher)`.
 Matcher throwsA(matcher) => new Throws(wrapMatcher(matcher));
@@ -49,13 +51,19 @@
     }
 
     if (item is Future) {
-      return item.then(
-          (value) => indent(prettyPrint(value), first: 'emitted '),
+      return item.then((value) => indent(prettyPrint(value), first: 'emitted '),
           onError: _check);
     }
 
     try {
       var value = item();
+      if (value is Future) {
+        return value.then(
+            (value) => indent(prettyPrint(value),
+                first: 'returned a Future that emitted '),
+            onError: _check);
+      }
+
       return indent(prettyPrint(value), first: 'returned ');
     } catch (error, trace) {
       return _check(error, trace);
@@ -83,7 +91,7 @@
         .toString();
 
     var buffer = new StringBuffer();
-    buffer.writeln(indent(prettyPrint(error),            first: 'threw '));
+    buffer.writeln(indent(prettyPrint(error), first: 'threw '));
     if (trace != null) {
       buffer.writeln(indent(testChain(trace).toString(), first: 'stack '));
     }
diff --git a/pub/test/lib/src/frontend/timeout.dart b/pub/test/lib/src/frontend/timeout.dart
index 6366937..cebcdae 100644
--- a/pub/test/lib/src/frontend/timeout.dart
+++ b/pub/test/lib/src/frontend/timeout.dart
@@ -43,12 +43,10 @@
   final num scaleFactor;
 
   /// Declares an absolute timeout that overrides the default.
-  const Timeout(this.duration)
-      : scaleFactor = null;
+  const Timeout(this.duration) : scaleFactor = null;
 
   /// Declares a relative timeout that scales the default.
-  const Timeout.factor(this.scaleFactor)
-      : duration = null;
+  const Timeout.factor(this.scaleFactor) : duration = null;
 
   const Timeout._none()
       : scaleFactor = null,
@@ -108,13 +106,20 @@
   /// Returns the number of microseconds in [number] [unit]s.
   static double _microsecondsFor(double number, String unit) {
     switch (unit) {
-      case "d": return number * 24 * 60 * 60 * 1000000;
-      case "h": return number * 60 * 60 * 1000000;
-      case "m": return number * 60 * 1000000;
-      case "s": return number * 1000000;
-      case "ms": return number * 1000;
-      case "us": return number;
-      default: throw new ArgumentError("Unknown unit $unit.");
+      case "d":
+        return number * 24 * 60 * 60 * 1000000;
+      case "h":
+        return number * 60 * 60 * 1000000;
+      case "m":
+        return number * 60 * 1000000;
+      case "s":
+        return number * 1000000;
+      case "ms":
+        return number * 1000;
+      case "us":
+        return number;
+      default:
+        throw new ArgumentError("Unknown unit $unit.");
     }
   }
 
@@ -141,7 +146,9 @@
 
   int get hashCode => duration.hashCode ^ 5 * scaleFactor.hashCode;
 
-  bool operator==(other) => other is Timeout && other.duration == duration &&
+  bool operator ==(other) =>
+      other is Timeout &&
+      other.duration == duration &&
       other.scaleFactor == scaleFactor;
 
   String toString() {
diff --git a/pub/test/lib/src/runner.dart b/pub/test/lib/src/runner.dart
index 8424bb1..0b63e5c 100644
--- a/pub/test/lib/src/runner.dart
+++ b/pub/test/lib/src/runner.dart
@@ -16,6 +16,7 @@
 import 'backend/test_platform.dart';
 import 'runner/application_exception.dart';
 import 'runner/configuration.dart';
+import 'runner/configuration/reporters.dart';
 import 'runner/debugger.dart';
 import 'runner/engine.dart';
 import 'runner/load_exception.dart';
@@ -24,7 +25,6 @@
 import 'runner/reporter.dart';
 import 'runner/reporter/compact.dart';
 import 'runner/reporter/expanded.dart';
-import 'runner/reporter/json.dart';
 import 'util/io.dart';
 import 'utils.dart';
 
@@ -67,30 +67,11 @@
 
   /// Creates a new runner based on [configuration].
   factory Runner(Configuration config) => config.asCurrent(() {
-    var engine = new Engine(concurrency: config.concurrency);
+        var engine = new Engine(concurrency: config.concurrency);
 
-    var reporter;
-    switch (config.reporter) {
-      case "expanded":
-        reporter = ExpandedReporter.watch(
-            engine,
-            color: config.color,
-            printPath: config.paths.length > 1 ||
-                new Directory(config.paths.single).existsSync(),
-            printPlatform: config.suiteDefaults.platforms.length > 1);
-        break;
-
-      case "compact":
-        reporter = CompactReporter.watch(engine);
-        break;
-
-      case "json":
-        reporter = JsonReporter.watch(engine);
-        break;
-    }
-
-    return new Runner._(engine, reporter);
-  });
+        var reporterDetails = allReporters[config.reporter];
+        return new Runner._(engine, reporterDetails.factory(config, engine));
+      });
 
   Runner._(this._engine, this._reporter);
 
@@ -99,44 +80,46 @@
   /// This starts running tests and printing their progress. It returns whether
   /// or not they ran successfully.
   Future<bool> run() => _config.asCurrent(() async {
-    if (_closed) {
-      throw new StateError("run() may not be called on a closed Runner.");
-    }
+        if (_closed) {
+          throw new StateError("run() may not be called on a closed Runner.");
+        }
 
-    _warnForUnsupportedPlatforms();
+        _warnForUnsupportedPlatforms();
 
-    var suites = _loadSuites();
+        var suites = _loadSuites();
 
-    var success;
-    if (_config.pauseAfterLoad) {
-      success = await _loadThenPause(suites);
-    } else {
-      _suiteSubscription = suites.listen(_engine.suiteSink.add);
-      var results = await Future.wait([
-        _suiteSubscription.asFuture().then((_) => _engine.suiteSink.close()),
-        _engine.run()
-      ], eagerError: true);
-      success = results.last;
-    }
+        var success;
+        if (_config.pauseAfterLoad) {
+          success = await _loadThenPause(suites);
+        } else {
+          _suiteSubscription = suites.listen(_engine.suiteSink.add);
+          var results = await Future.wait(<Future>[
+            _suiteSubscription
+                .asFuture()
+                .then((_) => _engine.suiteSink.close()),
+            _engine.run()
+          ], eagerError: true);
+          success = results.last;
+        }
 
-    if (_closed) return false;
+        if (_closed) return false;
 
-    if (_engine.passed.length == 0 &&
-        _engine.failed.length == 0 &&
-        _engine.skipped.length == 0 &&
-        _config.suiteDefaults.patterns.isNotEmpty) {
-      var patterns = toSentence(_config.suiteDefaults.patterns.map(
-          (pattern) => pattern is RegExp
-              ? 'regular expression "${pattern.pattern}"'
-              : '"$pattern"'));
+        if (_engine.passed.length == 0 &&
+            _engine.failed.length == 0 &&
+            _engine.skipped.length == 0 &&
+            _config.suiteDefaults.patterns.isNotEmpty) {
+          var patterns = toSentence(_config.suiteDefaults.patterns.map(
+              (pattern) => pattern is RegExp
+                  ? 'regular expression "${pattern.pattern}"'
+                  : '"$pattern"'));
 
-      throw new ApplicationException('No tests match $patterns.');
-    }
+          throw new ApplicationException('No tests match $patterns.');
+        }
 
-    // Explicitly check "== true" here because [Engine.run] can return `null`
-    // if the engine was closed prematurely.
-    return success == true;
-  });
+        // Explicitly check "== true" here because [Engine.run] can return `null`
+        // if the engine was closed prematurely.
+        return success == true;
+      });
 
   /// Emits a warning if the user is trying to run on a platform that's
   /// unsupported for the entire package.
@@ -155,16 +138,16 @@
     // If the user tried to run on one or moe unsupported browsers, figure out
     // whether we should warn about the individual browsers or whether all
     // browsers are unsupported.
-    var unsupportedBrowsers = unsupportedPlatforms
-        .where((platform) => platform.isBrowser);
+    var unsupportedBrowsers =
+        unsupportedPlatforms.where((platform) => platform.isBrowser);
     if (unsupportedBrowsers.isNotEmpty) {
       var supportsAnyBrowser = TestPlatform.all
           .where((platform) => platform.isBrowser)
           .any((platform) => testOn.evaluate(platform));
 
       if (supportsAnyBrowser) {
-        unsupportedNames.addAll(
-            unsupportedBrowsers.map((platform) => platform.name));
+        unsupportedNames
+            .addAll(unsupportedBrowsers.map((platform) => platform.name));
       } else {
         unsupportedNames.add("browsers");
       }
@@ -173,8 +156,8 @@
     // If the user tried to run on the VM and it's not supported, figure out if
     // that's because of the current OS or whether the VM is unsupported.
     if (unsupportedPlatforms.contains(TestPlatform.vm)) {
-      var supportsAnyOS = OperatingSystem.all.any((os) =>
-          testOn.evaluate(TestPlatform.vm, os: os));
+      var supportsAnyOS = OperatingSystem.all
+          .any((os) => testOn.evaluate(TestPlatform.vm, os: os));
 
       if (supportsAnyOS) {
         unsupportedNames.add(currentOS.name);
@@ -184,7 +167,8 @@
     }
 
     warn("this package doesn't support running tests on " +
-        toSentence(unsupportedNames, conjunction: "or") + ".");
+        toSentence(unsupportedNames, conjunction: "or") +
+        ".");
   }
 
   /// Closes the runner.
@@ -193,38 +177,35 @@
   /// currently-running VM tests, in case they have stuff to clean up on the
   /// filesystem.
   Future close() => _closeMemo.runOnce(() async {
-    var timer;
-    if (!_engine.isIdle) {
-      // Wait a bit to print this message, since printing it eagerly looks weird
-      // if the tests then finish immediately.
-      timer = new Timer(new Duration(seconds: 1), () {
-        // Pause the reporter while we print to ensure that we don't interfere
-        // with its output.
-        _reporter.pause();
-        print("Waiting for current test(s) to finish.");
-        print("Press Control-C again to terminate immediately.");
-        _reporter.resume();
+        var timer;
+        if (!_engine.isIdle) {
+          // Wait a bit to print this message, since printing it eagerly looks weird
+          // if the tests then finish immediately.
+          timer = new Timer(new Duration(seconds: 1), () {
+            // Pause the reporter while we print to ensure that we don't interfere
+            // with its output.
+            _reporter.pause();
+            print("Waiting for current test(s) to finish.");
+            print("Press Control-C again to terminate immediately.");
+            _reporter.resume();
+          });
+        }
+
+        if (_debugOperation != null) await _debugOperation.cancel();
+
+        if (_suiteSubscription != null) _suiteSubscription.cancel();
+        _suiteSubscription = null;
+
+        // Make sure we close the engine *before* the loader. Otherwise,
+        // LoadSuites provided by the loader may get into bad states.
+        //
+        // We close the loader's browsers while we're closing the engine because
+        // browser tests don't store any state we care about and we want them to
+        // shut down without waiting for their tear-downs.
+        await Future.wait([_loader.closeEphemeral(), _engine.close()]);
+        if (timer != null) timer.cancel();
+        await _loader.close();
       });
-    }
-
-    if (_debugOperation != null) await _debugOperation.cancel();
-
-    if (_suiteSubscription != null) _suiteSubscription.cancel();
-    _suiteSubscription = null;
-
-    // Make sure we close the engine *before* the loader. Otherwise,
-    // LoadSuites provided by the loader may get into bad states.
-    //
-    // We close the loader's browsers while we're closing the engine because
-    // browser tests don't store any state we care about and we want them to
-    // shut down without waiting for their tear-downs.
-    await Future.wait([
-      _loader.closeEphemeral(),
-      _engine.close()
-    ]);
-    if (timer != null) timer.cancel();
-    await _loader.close();
-  });
 
   /// Return a stream of [LoadSuite]s in [_config.paths].
   ///
@@ -239,8 +220,7 @@
       } else {
         return new Stream.fromIterable([
           new LoadSuite.forLoadException(
-              new LoadException(path, 'Does not exist.'),
-              _config.suiteDefaults)
+              new LoadException(path, 'Does not exist.'), _config.suiteDefaults)
         ]);
       }
     })).map((loadSuite) {
@@ -318,8 +298,8 @@
 
     collect(entry) {
       var newTags = new Set<String>();
-      for (var unknownTag in
-          entry.metadata.tags.difference(_config.knownTags)) {
+      for (var unknownTag
+          in entry.metadata.tags.difference(_config.knownTags)) {
         if (currentTags.contains(unknownTag)) continue;
         unknownTags.putIfAbsent(unknownTag, () => []).add(entry);
         newTags.add(unknownTag);
@@ -381,7 +361,7 @@
       await _debugOperation.valueOrCancellation();
     }).listen(null);
 
-    var results = await Future.wait([
+    var results = await Future.wait(<Future>[
       _suiteSubscription.asFuture().then((_) => _engine.suiteSink.close()),
       _engine.run()
     ], eagerError: true);
diff --git a/pub/test/lib/src/runner/browser/browser.dart b/pub/test/lib/src/runner/browser/browser.dart
index 3019dca..be07d8a 100644
--- a/pub/test/lib/src/runner/browser/browser.dart
+++ b/pub/test/lib/src/runner/browser/browser.dart
@@ -108,7 +108,22 @@
   /// exceptions.
   Future close() {
     _closed = true;
-    _process.then((process) => process.kill());
+
+    _process.then((process) {
+      // Dartium has a difficult time being killed on Linux. To ensure it is
+      // properly closed, find all children processes and kill those first.
+      try {
+        if (Platform.isLinux) {
+          var result = Process.runSync('pgrep', ['-P', '${process.pid}']);
+          for (var pid in '${result.stdout}'.split('\n')) {
+            Process.runSync('kill', ['-9', pid]);
+          }
+        }
+      } catch (e) {
+        print('Failed to kill browser children: $e');
+      }
+      process.kill();
+    });
 
     // Swallow exceptions. The user should explicitly use [onExit] for these.
     return onExit.catchError((_) {});
diff --git a/pub/test/lib/src/runner/browser/browser_manager.dart b/pub/test/lib/src/runner/browser/browser_manager.dart
index 05988d9..7f25b38 100644
--- a/pub/test/lib/src/runner/browser/browser_manager.dart
+++ b/pub/test/lib/src/runner/browser/browser_manager.dart
@@ -95,8 +95,9 @@
   ///
   /// Returns the browser manager, or throws an [ApplicationException] if a
   /// connection fails to be established.
-  static Future<BrowserManager> start(TestPlatform platform, Uri url,
-      Future<WebSocketChannel> future, {bool debug: false}) {
+  static Future<BrowserManager> start(
+      TestPlatform platform, Uri url, Future<WebSocketChannel> future,
+      {bool debug: false}) {
     var browser = _newBrowser(url, platform, debug: debug);
 
     var completer = new Completer<BrowserManager>();
@@ -133,14 +134,20 @@
   static Browser _newBrowser(Uri url, TestPlatform browser,
       {bool debug: false}) {
     switch (browser) {
-      case TestPlatform.dartium: return new Dartium(url, debug: debug);
+      case TestPlatform.dartium:
+        return new Dartium(url, debug: debug);
       case TestPlatform.contentShell:
         return new ContentShell(url, debug: debug);
-      case TestPlatform.chrome: return new Chrome(url, debug: debug);
-      case TestPlatform.phantomJS: return new PhantomJS(url, debug: debug);
-      case TestPlatform.firefox: return new Firefox(url);
-      case TestPlatform.safari: return new Safari(url);
-      case TestPlatform.internetExplorer: return new InternetExplorer(url);
+      case TestPlatform.chrome:
+        return new Chrome(url, debug: debug);
+      case TestPlatform.phantomJS:
+        return new PhantomJS(url, debug: debug);
+      case TestPlatform.firefox:
+        return new Firefox(url);
+      case TestPlatform.safari:
+        return new Safari(url);
+      case TestPlatform.internetExplorer:
+        return new InternetExplorer(url);
       default:
         throw new ArgumentError("$browser is not a browser.");
     }
@@ -159,12 +166,13 @@
       for (var controller in _controllers) {
         controller.setDebugging(true);
       }
-    })..cancel();
+    })
+      ..cancel();
 
     // Whenever we get a message, no matter which child channel it's for, we the
     // know browser is still running code which means the user isn't debugging.
-    _channel = new MultiChannel(webSocket.transform(jsonDocument)
-        .changeStream((stream) {
+    _channel = new MultiChannel(
+        webSocket.transform(jsonDocument).changeStream((stream) {
       return stream.map((message) {
         if (!_closed) _timer.reset();
         for (var controller in _controllers) {
@@ -195,7 +203,8 @@
   /// from this test suite.
   Future<RunnerSuite> load(String path, Uri url, SuiteConfiguration suiteConfig,
       {StackTraceMapper mapper}) async {
-    url = url.replace(fragment: Uri.encodeFull(JSON.encode({
+    url = url.replace(
+        fragment: Uri.encodeFull(JSON.encode({
       "metadata": suiteConfig.metadata.serialize(),
       "browser": _platform.identifier
     })));
@@ -205,21 +214,18 @@
     closeIframe() {
       if (_closed) return;
       _controllers.remove(controller);
-      _channel.sink.add({
-        "command": "closeSuite",
-        "id": suiteID
-      });
+      _channel.sink.add({"command": "closeSuite", "id": suiteID});
     }
 
     // The virtual channel will be closed when the suite is closed, in which
     // case we should unload the iframe.
     var suiteChannel = _channel.virtualChannel();
     var suiteChannelID = suiteChannel.id;
-    suiteChannel = suiteChannel.transformStream(
-        new StreamTransformer.fromHandlers(handleDone: (sink) {
-          closeIframe();
-          sink.close();
-        }));
+    suiteChannel = suiteChannel
+        .transformStream(new StreamTransformer.fromHandlers(handleDone: (sink) {
+      closeIframe();
+      sink.close();
+    }));
 
     return await _pool.withResource/*<Future<RunnerSuite>>*/(() async {
       _channel.sink.add({
@@ -263,7 +269,8 @@
   /// The callback for handling messages received from the host page.
   void _onMessage(Map message) {
     switch (message["command"]) {
-      case "ping": break;
+      case "ping":
+        break;
 
       case "restart":
         _onRestartController.add(null);
@@ -283,13 +290,13 @@
   /// Closes the manager and releases any resources it owns, including closing
   /// the browser.
   Future close() => _closeMemoizer.runOnce(() {
-    _closed = true;
-    _timer.cancel();
-    if (_pauseCompleter != null) _pauseCompleter.complete();
-    _pauseCompleter = null;
-    _controllers.clear();
-    return _browser.close();
-  });
+        _closed = true;
+        _timer.cancel();
+        if (_pauseCompleter != null) _pauseCompleter.complete();
+        _pauseCompleter = null;
+        _controllers.clear();
+        return _browser.close();
+      });
   final _closeMemoizer = new AsyncMemoizer();
 }
 
diff --git a/pub/test/lib/src/runner/browser/chrome.dart b/pub/test/lib/src/runner/browser/chrome.dart
index 0991c9d..7c984f1 100644
--- a/pub/test/lib/src/runner/browser/chrome.dart
+++ b/pub/test/lib/src/runner/browser/chrome.dart
@@ -8,7 +8,6 @@
 import 'package:path/path.dart' as p;
 
 import '../../util/io.dart';
-import '../../utils.dart';
 import 'browser.dart';
 
 // TODO(nweiz): move this into its own package?
@@ -37,43 +36,27 @@
       var tryPort = ([int port]) async {
         var dir = createTempDir();
         var args = [
-          "--user-data-dir=$dir", url.toString(), "--disable-extensions",
-          "--disable-popup-blocking", "--bwsi", "--no-first-run",
-          "--no-default-browser-check", "--disable-default-apps",
+          "--user-data-dir=$dir",
+          url.toString(),
+          "--disable-extensions",
+          "--disable-popup-blocking",
+          "--bwsi",
+          "--no-first-run",
+          "--no-default-browser-check",
+          "--disable-default-apps",
           "--disable-translate",
         ];
 
-        if (port != null) {
-          args.add("--remote-debugging-port=$port");
-          // These flags cause Chrome to print a consistent line of output after
-          // its internal call to `bind()` has succeeded or failed. We wait for
-          // that output to determine whether the port we chose worked.
-          args.add("--enable-logging=stderr");
-          args.add("--vmodule=startup_browser_creator_impl=1");
-        }
+        // Currently, Chrome doesn't provide any way of ensuring that this port
+        // was successfully bound. It produces an error if the binding fails,
+        // but without a reliable and fast way to tell if it succeeded that
+        // doesn't provide us much. It's very unlikely that this port will fail,
+        // though.
+        if (port != null) args.add("--remote-debugging-port=$port");
 
         var process = await Process.start(executable, args);
 
         if (port != null) {
-          var stderr = new StreamIterator(lineSplitter.bind(process.stderr));
-
-          // Before we can consider Chrome to have started successfully, we have
-          // to make sure the remote debugging port worked. Any errors from this
-          // will always come before the "startup_browser_creater_impl" message.
-          while (await stderr.moveNext() &&
-              !stderr.current.contains("startup_browser_creator_impl")) {
-            if (stderr.current.contains("bind() returned an error")) {
-              // If we failed to bind to the port, return null to tell
-              // getUnusedPort to try another one.
-              stderr.cancel();
-              process.kill();
-              return null;
-            }
-          }
-          stderr.cancel();
-        }
-
-        if (port != null) {
           remoteDebuggerCompleter.complete(
               getRemoteDebuggerUrl(Uri.parse("http://localhost:$port")));
         } else {
diff --git a/pub/test/lib/src/runner/browser/compiler_pool.dart b/pub/test/lib/src/runner/browser/compiler_pool.dart
index 76dcfa1..736da08 100644
--- a/pub/test/lib/src/runner/browser/compiler_pool.dart
+++ b/pub/test/lib/src/runner/browser/compiler_pool.dart
@@ -48,8 +48,8 @@
   ///
   /// The returned [Future] will complete once the `dart2js` process completes
   /// *and* all its output has been printed to the command line.
-  Future compile(String dartPath, String jsPath,
-      SuiteConfiguration suiteConfig) {
+  Future compile(
+      String dartPath, String jsPath, SuiteConfiguration suiteConfig) {
     return _pool.withResource(() {
       if (_closed) return null;
 
@@ -136,7 +136,8 @@
   /// them to [buffer].
   Future _printOutputStream(Stream<List<int>> stream, StringBuffer buffer) {
     return sanitizeForWindows(stream)
-        .listen((data) => buffer.write(UTF8.decode(data))).asFuture();
+        .listen((data) => buffer.write(UTF8.decode(data)))
+        .asFuture();
   }
 
   /// Closes the compiler pool.
diff --git a/pub/test/lib/src/runner/browser/content_shell.dart b/pub/test/lib/src/runner/browser/content_shell.dart
index b60ae6c..49a8228 100644
--- a/pub/test/lib/src/runner/browser/content_shell.dart
+++ b/pub/test/lib/src/runner/browser/content_shell.dart
@@ -36,16 +36,19 @@
         var args = ["--dump-render-tree", url.toString()];
         if (port != null) args.add("--remote-debugging-port=$port");
 
-        var process = await Process.start(executable, args,
-            environment: {"DART_FLAGS": "--checked"});
+        var process = await Process
+            .start(executable, args, environment: {"DART_FLAGS": "--checked"});
 
         if (debug) {
-          observatoryCompleter.complete(lineSplitter.bind(process.stdout)
+          observatoryCompleter.complete(lineSplitter
+              .bind(process.stdout)
               .map((line) {
-            var match = _observatoryRegExp.firstMatch(line);
-            if (match == null) return null;
-            return Uri.parse(match[1]);
-          }).where((uri) => uri != null).first);
+                var match = _observatoryRegExp.firstMatch(line);
+                if (match == null) return null;
+                return Uri.parse(match[1]);
+              })
+              .where((uri) => uri != null)
+              .first);
         } else {
           observatoryCompleter.complete(null);
         }
@@ -57,7 +60,8 @@
         // Any errors from this will always come before the "Running without
         // renderer sandbox" message.
         while (await stderr.moveNext() &&
-            !stderr.current.endsWith("Running without renderer sandbox")) {
+            !stderr.current.endsWith("Running without renderer sandbox") &&
+            !stderr.current.contains("Running without the SUID sandbox")) {
           if (stderr.current == "[dartToStderr]: Dartium build has expired") {
             stderr.cancel();
             process.kill();
@@ -66,9 +70,9 @@
             // (https://github.com/dart-lang/www.dartlang.org/issues/1164).
             throw new ApplicationException(
                 "You're using an expired content_shell. Upgrade to the latest "
-                    "version:\n"
+                "version:\n"
                 "http://gsdview.appspot.com/dart-archive/channels/stable/"
-                    "release/latest/dartium/");
+                "release/latest/dartium/");
           } else if (stderr.current.contains("bind() returned an error")) {
             // If we failed to bind to the port, return null to tell
             // getUnusedPort to try another one.
@@ -95,7 +99,7 @@
   }
 
   ContentShell._(Future<Process> startBrowser(), this.observatoryUrl,
-          this.remoteDebuggerUrl)
+      this.remoteDebuggerUrl)
       : super(startBrowser);
 
   /// Return the default executable for the current operating system.
diff --git a/pub/test/lib/src/runner/browser/dartium.dart b/pub/test/lib/src/runner/browser/dartium.dart
index 40edb22..3e8235b 100644
--- a/pub/test/lib/src/runner/browser/dartium.dart
+++ b/pub/test/lib/src/runner/browser/dartium.dart
@@ -39,9 +39,14 @@
       var tryPort = ([int port]) async {
         var dir = createTempDir();
         var args = [
-          "--user-data-dir=$dir", url.toString(), "--disable-extensions",
-          "--disable-popup-blocking", "--bwsi", "--no-first-run",
-          "--no-default-browser-check", "--disable-default-apps",
+          "--user-data-dir=$dir",
+          url.toString(),
+          "--disable-extensions",
+          "--disable-popup-blocking",
+          "--bwsi",
+          "--no-first-run",
+          "--no-default-browser-check",
+          "--disable-default-apps",
           "--disable-translate"
         ];
 
@@ -57,8 +62,8 @@
           args.add("--vmodule=startup_browser_creator_impl=1");
         }
 
-        var process = await Process.start(executable, args,
-            environment: {"DART_FLAGS": "--checked"});
+        var process = await Process
+            .start(executable, args, environment: {"DART_FLAGS": "--checked"});
 
         if (port != null) {
           // Dartium on Windows prints all standard IO to stderr, so we need to
@@ -116,7 +121,7 @@
   }
 
   Dartium._(Future<Process> startBrowser(), this.observatoryUrl,
-          this.remoteDebuggerUrl)
+      this.remoteDebuggerUrl)
       : super(startBrowser);
 
   /// Starts a new instance of Dartium open to the given [url], which may be a
@@ -148,8 +153,8 @@
         return null;
       }
 
-      var dartium = p.join(
-          dir, "chromium/Chromium.app/Contents/MacOS/Chromium");
+      var dartium =
+          p.join(dir, "chromium/Chromium.app/Contents/MacOS/Chromium");
       return new File(dartium).existsSync() ? dartium : null;
     }
 
@@ -176,11 +181,8 @@
       return match == null ? null : Uri.parse(match[1]);
     }).where((line) => line != null));
 
-    var operations = [
-      urlQueue.next,
-      urlQueue.next,
-      urlQueue.next
-    ].map((future) => _checkObservatoryUrl(future));
+    var operations = [urlQueue.next, urlQueue.next, urlQueue.next]
+        .map((future) => _checkObservatoryUrl(future));
 
     urlQueue.cancel();
 
@@ -214,8 +216,8 @@
 
     future.then((url) async {
       try {
-        webSocket = await WebSocket.connect(
-            url.replace(scheme: 'ws', path: '/ws').toString());
+        webSocket = await WebSocket
+            .connect(url.replace(scheme: 'ws', path: '/ws').toString());
         if (canceled) {
           webSocket.close();
           return null;
@@ -228,12 +230,8 @@
           "id": "0"
         }));
 
-        webSocket.add(JSON.encode({
-          "jsonrpc": "2.0",
-          "method": "getVM",
-          "params": {},
-          "id": "1"
-        }));
+        webSocket.add(JSON.encode(
+            {"jsonrpc": "2.0", "method": "getVM", "params": {}, "id": "1"}));
 
         webSocket.listen((response) {
           try {
diff --git a/pub/test/lib/src/runner/browser/firefox.dart b/pub/test/lib/src/runner/browser/firefox.dart
index f7aab95..5c9a016 100644
--- a/pub/test/lib/src/runner/browser/firefox.dart
+++ b/pub/test/lib/src/runner/browser/firefox.dart
@@ -40,13 +40,9 @@
     var dir = createTempDir();
     new File(p.join(dir, 'prefs.js')).writeAsStringSync(_preferences);
 
-    var process = await Process.start(executable, [
-      "--profile", "$dir",
-      url.toString(),
-      "--no-remote"
-    ], environment: {
-      "MOZ_CRASHREPORTER_DISABLE": "1"
-    });
+    var process = await Process.start(
+        executable, ["--profile", "$dir", url.toString(), "--no-remote"],
+        environment: {"MOZ_CRASHREPORTER_DISABLE": "1"});
 
     process.exitCode
         .then((_) => new Directory(dir).deleteSync(recursive: true));
diff --git a/pub/test/lib/src/runner/browser/phantom_js.dart b/pub/test/lib/src/runner/browser/phantom_js.dart
index a3097e0..640841d 100644
--- a/pub/test/lib/src/runner/browser/phantom_js.dart
+++ b/pub/test/lib/src/runner/browser/phantom_js.dart
@@ -54,10 +54,8 @@
 
       var args = <String>[];
       if (debug) {
-        args.addAll([
-          "--remote-debugger-port=$port",
-          "--remote-debugger-autorun=yes"
-        ]);
+        args.addAll(
+            ["--remote-debugger-port=$port", "--remote-debugger-autorun=yes"]);
       }
       args.addAll([script, url.toString()]);
       var process = await Process.start(executable, args);
diff --git a/pub/test/lib/src/runner/browser/platform.dart b/pub/test/lib/src/runner/browser/platform.dart
index 31dc749..839211c 100644
--- a/pub/test/lib/src/runner/browser/platform.dart
+++ b/pub/test/lib/src/runner/browser/platform.dart
@@ -39,8 +39,7 @@
   ///
   /// [root] is the root directory that the server should serve. It defaults to
   /// the working directory.
-  static Future<BrowserPlatform> start({String root})
-      async {
+  static Future<BrowserPlatform> start({String root}) async {
     var server = new shelf_io.IOServer(await HttpMultiServer.loopback(0));
     return new BrowserPlatform._(server, Configuration.current, root: root);
   }
@@ -94,12 +93,10 @@
   bool get _closed => _closeMemo.hasRun;
 
   /// A map from browser identifiers to futures that will complete to the
-  /// [BrowserManager]s for those browsers, or the errors that occurred when
-  /// trying to load those managers.
+  /// [BrowserManager]s for those browsers, or `null` if they failed to load.
   ///
   /// This should only be accessed through [_browserManagerFor].
-  final _browserManagers =
-      new Map<TestPlatform, Future<Result<BrowserManager>>>();
+  final _browserManagers = new Map<TestPlatform, Future<BrowserManager>>();
 
   /// A cascade of handlers for suites' precompiled paths.
   ///
@@ -125,8 +122,7 @@
         _compiledDir = config.pubServeUrl == null ? createTempDir() : null,
         _http = config.pubServeUrl == null ? null : new HttpClient(),
         _compilers = new CompilerPool() {
-    var cascade = new shelf.Cascade()
-        .add(_webSocketHandler.handler);
+    var cascade = new shelf.Cascade().add(_webSocketHandler.handler);
 
     if (_config.pubServeUrl == null) {
       cascade = cascade
@@ -136,7 +132,8 @@
 
           // Add this before the wrapper handler so that its HTML takes
           // precedence over the test runner's.
-          .add((request) => _precompiledCascade?.handler(request) ??
+          .add((request) =>
+              _precompiledCascade?.handler(request) ??
               new shelf.Response.notFound(null))
           .add(_wrapperHandler);
     }
@@ -154,7 +151,8 @@
 
     if (path.endsWith(".browser_test.dart")) {
       var testPath = p.basename(p.withoutExtension(p.withoutExtension(path)));
-      return new shelf.Response.ok('''
+      return new shelf.Response.ok(
+          '''
         import "package:stream_channel/stream_channel.dart";
 
         import "package:test/src/runner/plugin/remote_platform_helpers.dart";
@@ -166,7 +164,8 @@
           var channel = serializeSuite(() => test.main, hidePrints: false);
           postMessageChannel().pipe(channel);
         }
-      ''', headers: {'Content-Type': 'application/dart'});
+      ''',
+          headers: {'Content-Type': 'application/dart'});
     }
 
     if (path.endsWith(".html")) {
@@ -180,7 +179,8 @@
           ? 'type="application/dart" src="$scriptBase"'
           : 'src="$scriptBase.js"';
 
-      return new shelf.Response.ok('''
+      return new shelf.Response.ok(
+          '''
         <!DOCTYPE html>
         <html>
         <head>
@@ -188,7 +188,8 @@
           <script $script></script>
         </head>
         </html>
-      ''', headers: {'Content-Type': 'text/html'});
+      ''',
+          headers: {'Content-Type': 'text/html'});
     }
 
     return new shelf.Response.notFound('Not found.');
@@ -198,8 +199,8 @@
   ///
   /// This will start a browser to load the suite if one isn't already running.
   /// Throws an [ArgumentError] if [browser] isn't a browser platform.
-  Future<RunnerSuite> load(String path, TestPlatform browser,
-      SuiteConfiguration suiteConfig) async {
+  Future<RunnerSuite> load(
+      String path, TestPlatform browser, SuiteConfiguration suiteConfig) async {
     assert(suiteConfig.platforms.contains(browser));
 
     if (!browser.isBrowser) {
@@ -208,18 +209,21 @@
 
     var htmlPath = p.withoutExtension(path) + '.html';
     if (new File(htmlPath).existsSync() &&
-        !new File(htmlPath).readAsStringSync()
+        !new File(htmlPath)
+            .readAsStringSync()
             .contains('packages/test/dart.js')) {
       throw new LoadException(
           path,
           '"${htmlPath}" must contain <script src="packages/test/dart.js">'
-              '</script>.');
+          '</script>.');
     }
 
     var suiteUrl;
     if (_config.pubServeUrl != null) {
-      var suitePrefix = p.toUri(p.withoutExtension(
-          p.relative(path, from: p.join(_root, 'test')))).path;
+      var suitePrefix = p
+          .toUri(
+              p.withoutExtension(p.relative(path, from: p.join(_root, 'test'))))
+          .path;
 
       var dartUrl;
       // Polymer generates a bootstrap entrypoint that wraps the entrypoint we
@@ -231,8 +235,8 @@
         dartUrl = _config.pubServeUrl.resolve(
             "$suitePrefix.html.polymer.bootstrap.dart.browser_test.dart");
       } else {
-        dartUrl = _config.pubServeUrl.resolve(
-          '$suitePrefix.dart.browser_test.dart');
+        dartUrl =
+            _config.pubServeUrl.resolve('$suitePrefix.dart.browser_test.dart');
       }
 
       await _pubServeSuite(path, dartUrl, browser, suiteConfig);
@@ -255,8 +259,8 @@
               }
             }
             _precompiledCascade ??= new shelf.Cascade();
-            _precompiledCascade = _precompiledCascade.add(
-                createStaticHandler(suiteConfig.precompiledPath));
+            _precompiledCascade = _precompiledCascade
+                .add(createStaticHandler(suiteConfig.precompiledPath));
           }
         } else {
           await _compileSuite(path, suiteConfig);
@@ -264,15 +268,15 @@
       }
 
       if (_closed) return null;
-      suiteUrl = url.resolveUri(p.toUri(
-          p.withoutExtension(p.relative(path, from: _root)) + ".html"));
+      suiteUrl = url.resolveUri(
+          p.toUri(p.withoutExtension(p.relative(path, from: _root)) + ".html"));
     }
 
     if (_closed) return null;
 
     // TODO(nweiz): Don't start the browser until all the suites are compiled.
     var browserManager = await _browserManagerFor(browser);
-    if (_closed) return null;
+    if (_closed || browserManager == null) return null;
 
     var suite = await browserManager.load(path, suiteUrl, suiteConfig,
         mapper: browser.isJS ? _mappers[path] : null);
@@ -284,8 +288,7 @@
   /// underneath [suiteConfig.precompiledPath].
   bool _precompiled(SuiteConfiguration suiteConfig, String path) {
     if (suiteConfig.precompiledPath == null) return false;
-    var htmlPath = p.join(
-        suiteConfig.precompiledPath,
+    var htmlPath = p.join(suiteConfig.precompiledPath,
         p.relative(p.withoutExtension(path) + ".html", from: _root));
     return new File(htmlPath).existsSync();
   }
@@ -324,9 +327,10 @@
           // else the process can't exit.
           response.listen((_) {});
 
-          throw new LoadException(path,
+          throw new LoadException(
+              path,
               "Error getting $url: ${response.statusCode} "
-                  "${response.reasonPhrase}\n"
+              "${response.reasonPhrase}\n"
               'Make sure "pub serve" is serving the test/ directory.');
         }
 
@@ -334,9 +338,8 @@
           _mappers[path] = new StackTraceMapper(
               await UTF8.decodeStream(response),
               mapUrl: url,
-              packageResolver: new SyncPackageResolver.root(
-                  _config.pubServeUrl.resolve('packages')),
-              sdkRoot: _config.pubServeUrl.resolve('packages/\$sdk'));
+              packageResolver: new SyncPackageResolver.root('packages'),
+              sdkRoot: p.toUri('packages/\$sdk'));
           return;
         }
 
@@ -349,7 +352,8 @@
               "(errno ${error.osError.errorCode})";
         }
 
-        throw new LoadException(path,
+        throw new LoadException(
+            path,
             "Error getting $url: $message\n"
             'Make sure "pub serve" is running.');
       } finally {
@@ -399,8 +403,8 @@
   ///
   /// If no browser manager is running yet, starts one.
   Future<BrowserManager> _browserManagerFor(TestPlatform platform) {
-    var manager = _browserManagers[platform];
-    if (manager != null) return Result.release(manager);
+    var managerFuture = _browserManagers[platform];
+    if (managerFuture != null) return managerFuture;
 
     var completer = new Completer<WebSocketChannel>.sync();
     var path = _webSocketHandler.create(webSocketHandler(completer.complete));
@@ -408,19 +412,16 @@
     var hostUrl = (_config.pubServeUrl == null ? url : _config.pubServeUrl)
         .resolve('packages/test/src/runner/browser/static/index.html')
         .replace(queryParameters: {
-          'managerUrl': webSocketUrl.toString(),
-          'debug': _config.pauseAfterLoad.toString()
-        });
+      'managerUrl': webSocketUrl.toString(),
+      'debug': _config.pauseAfterLoad.toString()
+    });
 
     var future = BrowserManager.start(platform, hostUrl, completer.future,
         debug: _config.pauseAfterLoad);
 
-    // Capture errors and release them later to avoid Zone issues. This call to
-    // [_browserManagerFor] is running in a different [LoadSuite] than future
-    // calls, which means they're also running in different error zones so
-    // errors can't be freely passed between them. Storing the error or value as
-    // an explicit [Result] fixes that.
-    _browserManagers[platform] = Result.capture(future);
+    // Store null values for browsers that error out so we know not to load them
+    // again.
+    _browserManagers[platform] = future.catchError((_) => null);
 
     return future;
   }
@@ -434,8 +435,8 @@
     _browserManagers.clear();
     return Future.wait(managers.map((manager) async {
       var result = await manager;
-      if (result.isError) return;
-      await result.asValue.value.close();
+      if (result == null) return;
+      await result.close();
     }));
   }
 
@@ -444,23 +445,24 @@
   /// Returns a [Future] that completes once the server is closed and its
   /// resources have been fully released.
   Future close() => _closeMemo.runOnce(() async {
-    var futures = _browserManagers.values.map((future) async {
-      var result = await future;
-      if (result.isError) return;
+        var futures =
+            _browserManagers.values.map<Future<dynamic>>((future) async {
+          var result = await future;
+          if (result == null) return;
 
-      await result.asValue.value.close();
-    }).toList();
+          await result.close();
+        }).toList();
 
-    futures.add(_server.close());
-    futures.add(_compilers.close());
+        futures.add(_server.close());
+        futures.add(_compilers.close());
 
-    await Future.wait(futures);
+        await Future.wait(futures);
 
-    if (_config.pubServeUrl == null) {
-      new Directory(_compiledDir).deleteSync(recursive: true);
-    } else {
-      _http.close();
-    }
-  });
+        if (_config.pubServeUrl == null) {
+          new Directory(_compiledDir).deleteSync(recursive: true);
+        } else {
+          _http.close();
+        }
+      });
   final _closeMemo = new AsyncMemoizer();
 }
diff --git a/pub/test/lib/src/runner/browser/post_message_channel.dart b/pub/test/lib/src/runner/browser/post_message_channel.dart
index 726ea6f..50149eb 100644
--- a/pub/test/lib/src/runner/browser/post_message_channel.dart
+++ b/pub/test/lib/src/runner/browser/post_message_channel.dart
@@ -25,18 +25,14 @@
   controller.local.stream.listen((data) {
     // TODO(nweiz): Stop manually adding href here once issue 22554 is
     // fixed.
-    window.parent.postMessage({
-      "href": window.location.href,
-      "data": data
-    }, window.location.origin);
+    window.parent.postMessage(
+        {"href": window.location.href, "data": data}, window.location.origin);
   });
 
   // Send a ready message once we're listening so the host knows it's safe to
   // start sending events.
-  window.parent.postMessage({
-    "href": window.location.href,
-    "ready": true
-  }, window.location.origin);
+  window.parent.postMessage(
+      {"href": window.location.href, "ready": true}, window.location.origin);
 
   return controller.foreign;
 }
diff --git a/pub/test/lib/src/runner/configuration.dart b/pub/test/lib/src/runner/configuration.dart
index bf839bb..1d89e30 100644
--- a/pub/test/lib/src/runner/configuration.dart
+++ b/pub/test/lib/src/runner/configuration.dart
@@ -16,6 +16,7 @@
 import '../util/io.dart';
 import 'configuration/args.dart' as args;
 import 'configuration/load.dart';
+import 'configuration/reporters.dart';
 import 'configuration/suite.dart';
 import 'configuration/values.dart';
 
@@ -126,6 +127,7 @@
     _knownTags = new UnmodifiableSetView(known);
     return _knownTags;
   }
+
   Set<String> _knownTags;
 
   /// Configuration presets.
@@ -152,6 +154,7 @@
     _knownPresets = new UnmodifiableSetView(known);
     return _knownPresets;
   }
+
   Set<String> _knownPresets;
 
   /// The default suite-level configuration.
@@ -179,8 +182,8 @@
   factory Configuration.load(String path, {bool global: false}) =>
       load(path, global: global);
 
-  factory Configuration({
-      bool help,
+  factory Configuration(
+      {bool help,
       bool version,
       bool pauseAfterLoad,
       bool color,
@@ -211,6 +214,7 @@
       // Test-level configuration
       Timeout timeout,
       bool verboseTrace,
+      bool chainStackTraces,
       bool skip,
       String skipReason,
       PlatformSelector testOn,
@@ -247,6 +251,7 @@
             // Test-level configuration
             timeout: timeout,
             verboseTrace: verboseTrace,
+            chainStackTraces: chainStackTraces,
             skip: skip,
             skipReason: skipReason,
             testOn: testOn,
@@ -257,30 +262,31 @@
   static Map<Object, Configuration> _withChosenPresets(
       Map<Object, Configuration> map, Set<String> chosenPresets) {
     if (map == null || chosenPresets == null) return map;
-    return mapMap(map, value: (_, config) => config.change(
-        chosenPresets: config.chosenPresets.union(chosenPresets)));
+    return mapMap(map,
+        value: (_, config) => config.change(
+            chosenPresets: config.chosenPresets.union(chosenPresets)));
   }
 
   /// Creates new Configuration.
   ///
   /// Unlike [new Configuration], this assumes [presets] is already resolved.
-  Configuration._({
-          bool help,
-          bool version,
-          bool pauseAfterLoad,
-          bool color,
-          String configurationPath,
-          String dart2jsPath,
-          String reporter,
-          int pubServePort,
-          int concurrency,
-          this.shardIndex,
-          this.totalShards,
-          Iterable<String> paths,
-          Glob filename,
-          Iterable<String> chosenPresets,
-          Map<String, Configuration> presets,
-          SuiteConfiguration suiteDefaults})
+  Configuration._(
+      {bool help,
+      bool version,
+      bool pauseAfterLoad,
+      bool color,
+      String configurationPath,
+      String dart2jsPath,
+      String reporter,
+      int pubServePort,
+      int concurrency,
+      this.shardIndex,
+      this.totalShards,
+      Iterable<String> paths,
+      Glob filename,
+      Iterable<String> chosenPresets,
+      Map<String, Configuration> presets,
+      SuiteConfiguration suiteDefaults})
       : _help = help,
         _version = version,
         _pauseAfterLoad = pauseAfterLoad,
@@ -294,17 +300,17 @@
         _concurrency = concurrency,
         _paths = _list(paths),
         _filename = filename,
-        chosenPresets = new UnmodifiableSetView(
-            chosenPresets?.toSet() ?? new Set()),
+        chosenPresets =
+            new UnmodifiableSetView(chosenPresets?.toSet() ?? new Set()),
         presets = _map(presets),
         suiteDefaults = pauseAfterLoad == true
             ? suiteDefaults?.change(timeout: Timeout.none) ??
-                  new SuiteConfiguration(timeout: Timeout.none)
+                new SuiteConfiguration(timeout: Timeout.none)
             : suiteDefaults ?? SuiteConfiguration.empty {
     if (_filename != null && _filename.context.style != p.style) {
       throw new ArgumentError(
           "filename's context must match the current operating system, was "
-              "${_filename.context.style}.");
+          "${_filename.context.style}.");
     }
 
     if ((shardIndex == null) != (totalShards == null)) {
@@ -327,7 +333,7 @@
   /// If [input] is `null` or empty, this returns `null`.
   static List/*<T>*/ _list/*<T>*/(Iterable/*<T>*/ input) {
     if (input == null) return null;
-    var list = new List/*<T>*/.unmodifiable(input);
+    var list = new List/*<T>*/ .unmodifiable(input);
     if (list.isEmpty) return null;
     return list;
   }
@@ -383,8 +389,8 @@
   ///
   /// Note that unlike [merge], this has no merging behavior—the old value is
   /// always replaced by the new one.
-  Configuration change({
-      bool help,
+  Configuration change(
+      {bool help,
       bool version,
       bool pauseAfterLoad,
       bool color,
@@ -415,6 +421,7 @@
       // Test-level configuration
       Timeout timeout,
       bool verboseTrace,
+      bool chainStackTraces,
       bool skip,
       String skipReason,
       PlatformSelector testOn,
@@ -448,6 +455,7 @@
             onPlatform: onPlatform,
             timeout: timeout,
             verboseTrace: verboseTrace,
+            chainStackTraces: chainStackTraces,
             skip: skip,
             skipReason: skipReason,
             testOn: testOn,
@@ -459,8 +467,8 @@
   ///
   /// Any overlapping keys in the maps have their configurations merged in the
   /// returned map.
-  Map<Object, Configuration> _mergeConfigMaps(Map<Object, Configuration> map1,
-          Map<Object, Configuration> map2) =>
+  Map<Object, Configuration> _mergeConfigMaps(
+          Map<Object, Configuration> map1, Map<Object, Configuration> map2) =>
       mergeMaps(map1, map2,
           value: (config1, config2) => config1.merge(config2));
 
@@ -470,8 +478,10 @@
     if (chosenPresets.isEmpty || presets.isEmpty) return this;
 
     var newPresets = new Map<String, Configuration>.from(presets);
-    var merged = chosenPresets.fold(empty, (merged, preset) =>
-        merged.merge(newPresets.remove(preset) ?? Configuration.empty));
+    var merged = chosenPresets.fold(
+        empty,
+        (merged, preset) =>
+            merged.merge(newPresets.remove(preset) ?? Configuration.empty));
 
     if (merged == empty) return this;
     var result = this.change(presets: newPresets).merge(merged);
diff --git a/pub/test/lib/src/runner/configuration/args.dart b/pub/test/lib/src/runner/configuration/args.dart
index 4b288a7..67a5efb 100644
--- a/pub/test/lib/src/runner/configuration/args.dart
+++ b/pub/test/lib/src/runner/configuration/args.dart
@@ -10,6 +10,7 @@
 import '../../backend/test_platform.dart';
 import '../../frontend/timeout.dart';
 import '../configuration.dart';
+import 'reporters.dart';
 import 'values.dart';
 
 /// The parser used to parse the command-line arguments.
@@ -20,10 +21,10 @@
   if (!Platform.isMacOS) allPlatforms.remove(TestPlatform.safari);
   if (!Platform.isWindows) allPlatforms.remove(TestPlatform.internetExplorer);
 
-  parser.addFlag("help", abbr: "h", negatable: false,
-      help: "Shows this usage information.");
-  parser.addFlag("version", negatable: false,
-      help: "Shows the package's version.");
+  parser.addFlag("help",
+      abbr: "h", negatable: false, help: "Shows this usage information.");
+  parser.addFlag("version",
+      negatable: false, help: "Shows the package's version.");
 
   // Note that defaultsTo declarations here are only for documentation purposes.
   // We pass null values rather than defaults to [new Configuration] so that it
@@ -85,21 +86,30 @@
           'Implies --concurrency=1 and --timeout=none.\n'
           'Currently only supported for browser tests.',
       negatable: false);
+  parser.addFlag("chain-stack-traces",
+      help: 'Chained stack traces to provide greater exception details\n'
+          'especially for asynchronous code. It may be useful to disable\n'
+          'to provide improved test performance but at the cost of\n'
+          'debuggability.',
+      defaultsTo: true);
+
+  var reporterDescriptions = <String, String>{};
+  for (var reporter in allReporters.keys) {
+    reporterDescriptions[reporter] = allReporters[reporter].description;
+  }
 
   parser.addSeparator("======== Output");
   parser.addOption("reporter",
       abbr: 'r',
       help: 'The runner used to print test results.',
       defaultsTo: defaultReporter,
-      allowed: allReporters,
-      allowedHelp: {
-    'compact': 'A single line, updated continuously.',
-    'expanded': 'A separate line for each update.',
-    'json': 'A machine-readable format (see https://goo.gl/gBsV1a).'
-  });
-  parser.addFlag("verbose-trace", negatable: false,
+      allowed: reporterDescriptions.keys.toList(),
+      allowedHelp: reporterDescriptions);
+  parser.addFlag("verbose-trace",
+      negatable: false,
       help: 'Whether to emit stack traces with core library frames.');
-  parser.addFlag("js-trace", negatable: false,
+  parser.addFlag("js-trace",
+      negatable: false,
       help: 'Whether to emit raw JavaScript stack traces for browser tests.');
   parser.addFlag("color",
       help: 'Whether to use terminal colors.\n(auto-detected by default)');
@@ -113,7 +123,8 @@
       help: 'The path to the dart2js executable.', hide: true);
   parser.addOption("dart2js-args",
       help: 'Extra arguments to pass to dart2js.',
-      allowMultiple: true, hide: true);
+      allowMultiple: true,
+      hide: true);
   parser.addOption("total-shards",
       help: 'The total number of invocations of the test runner being run.',
       hide: true);
@@ -154,7 +165,7 @@
         .map/*<Pattern>*/(
             (value) => _wrapFormatException('name', () => new RegExp(value)))
         .toList()
-        ..addAll(_options['plain-name'] as List<String>);
+          ..addAll(_options['plain-name'] as List<String>);
 
     var includeTagSet = new Set.from(_options['tags'] ?? [])
       ..addAll(_options['tag'] ?? []);
@@ -190,6 +201,7 @@
         help: _ifParsed('help'),
         version: _ifParsed('version'),
         verboseTrace: _ifParsed('verbose-trace'),
+        chainStackTraces: _ifParsed('chain-stack-traces'),
         jsTrace: _ifParsed('js-trace'),
         pauseAfterLoad: _ifParsed('pause-after-load'),
         color: _ifParsed('color'),
@@ -204,8 +216,8 @@
         totalShards: totalShards,
         timeout: _parseOption('timeout', (value) => new Timeout.parse(value)),
         patterns: patterns,
-        platforms: (_ifParsed('platform') as List<String>)
-            ?.map(TestPlatform.find),
+        platforms:
+            (_ifParsed('platform') as List<String>)?.map(TestPlatform.find),
         runSkipped: _ifParsed('run-skipped'),
         chosenPresets: _ifParsed('preset') as List<String>,
         paths: _options.rest.isEmpty ? null : _options.rest,
diff --git a/pub/test/lib/src/runner/configuration/load.dart b/pub/test/lib/src/runner/configuration/load.dart
index c514fdd..597fb35 100644
--- a/pub/test/lib/src/runner/configuration/load.dart
+++ b/pub/test/lib/src/runner/configuration/load.dart
@@ -15,11 +15,11 @@
 import '../../backend/platform_selector.dart';
 import '../../backend/test_platform.dart';
 import '../../frontend/timeout.dart';
-import '../../utils.dart';
 import '../../util/io.dart';
+import '../../utils.dart';
 import '../configuration.dart';
 import '../configuration/suite.dart';
-import 'values.dart';
+import 'reporters.dart';
 
 /// Loads configuration information from a YAML file at [path].
 ///
@@ -59,8 +59,8 @@
   /// Whether runner configuration is allowed at this level.
   final bool _runnerConfig;
 
-  _ConfigurationLoader(this._document, this._source, {bool global: false,
-          bool runnerConfig: true})
+  _ConfigurationLoader(this._document, this._source,
+      {bool global: false, bool runnerConfig: true})
       : _global = global,
         _runnerConfig = runnerConfig;
 
@@ -73,6 +73,7 @@
   /// Loads test configuration that's allowed in the global configuration file.
   Configuration _loadGlobalTestConfig() {
     var verboseTrace = _getBool("verbose_trace");
+    var chainStackTraces = _getBool("chain_stack_traces");
     var jsTrace = _getBool("js_trace");
 
     var timeout = _parseValue("timeout", (value) => new Timeout.parse(value));
@@ -83,17 +84,20 @@
         value: (valueNode) =>
             _nestedConfig(valueNode, "on_platform value", runnerConfig: false));
 
-    var onOS = _getMap("on_os", key: (keyNode) {
-      _validate(keyNode, "on_os key must be a string.",
-          (value) => value is String);
+    var onOS = _getMap("on_os",
+        key: (keyNode) {
+          _validate(keyNode, "on_os key must be a string.",
+              (value) => value is String);
 
-      var os = OperatingSystem.find(keyNode.value);
-      if (os != null) return os;
+          var os = OperatingSystem.find(keyNode.value);
+          if (os != null) return os;
 
-      throw new SourceSpanFormatException(
-          'Invalid on_os key: No such operating system.',
-          keyNode.span, _source);
-    }, value: (valueNode) => _nestedConfig(valueNode, "on_os value"));
+          throw new SourceSpanFormatException(
+              'Invalid on_os key: No such operating system.',
+              keyNode.span,
+              _source);
+        },
+        value: (valueNode) => _nestedConfig(valueNode, "on_os value"));
 
     var presets = _getMap("presets",
         key: (keyNode) => _parseIdentifierLike(keyNode, "presets key"),
@@ -103,9 +107,10 @@
             verboseTrace: verboseTrace,
             jsTrace: jsTrace,
             timeout: timeout,
-            presets: presets)
-        .merge(_extractPresets/*<PlatformSelector>*/(onPlatform,
-            (map) => new Configuration(onPlatform: map)));
+            presets: presets,
+            chainStackTraces: chainStackTraces)
+        .merge(_extractPresets/*<PlatformSelector>*/(
+            onPlatform, (map) => new Configuration(onPlatform: map)));
 
     var osConfig = onOS[currentOS];
     return osConfig == null ? config : config.merge(osConfig);
@@ -133,15 +138,15 @@
       skip = true;
     }
 
-    var testOn = _parseValue("test_on",
-        (value) => new PlatformSelector.parse(value));
+    var testOn =
+        _parseValue("test_on", (value) => new PlatformSelector.parse(value));
 
-    var addTags = _getList("add_tags",
-        (tagNode) => _parseIdentifierLike(tagNode, "Tag name"));
+    var addTags = _getList(
+        "add_tags", (tagNode) => _parseIdentifierLike(tagNode, "Tag name"));
 
     var tags = _getMap("tags",
-        key: (keyNode) => _parseNode(keyNode, "tags key",
-            (value) => new BooleanSelector.parse(value)),
+        key: (keyNode) => _parseNode(
+            keyNode, "tags key", (value) => new BooleanSelector.parse(value)),
         value: (valueNode) =>
             _nestedConfig(valueNode, "tag value", runnerConfig: false));
 
@@ -150,8 +155,8 @@
             skipReason: skipReason,
             testOn: testOn,
             addTags: addTags)
-        .merge(_extractPresets/*<BooleanSelector>*/(tags,
-            (map) => new Configuration(tags: map)));
+        .merge(_extractPresets/*<BooleanSelector>*/(
+            tags, (map) => new Configuration(tags: map)));
   }
 
   /// Loads runner configuration that's allowed in the global configuration
@@ -175,7 +180,7 @@
     var runSkipped = _getBool("run_skipped");
 
     var reporter = _getString("reporter");
-    if (reporter != null && !allReporters.contains(reporter)) {
+    if (reporter != null && !allReporters.keys.contains(reporter)) {
       _error('Unknown reporter "$reporter".', "reporter");
     }
 
@@ -226,10 +231,12 @@
     var patterns = _getList("names", (nameNode) {
       _validate(nameNode, "Names must be strings.", (value) => value is String);
       return _parseNode(nameNode, "name", (value) => new RegExp(value));
-    })..addAll(_getList("plain_names", (nameNode) {
-      _validate(nameNode, "Names must be strings.", (value) => value is String);
-      return nameNode.value;
-    }));
+    })
+      ..addAll(_getList("plain_names", (nameNode) {
+        _validate(
+            nameNode, "Names must be strings.", (value) => value is String);
+        return nameNode.value;
+      }));
 
     var paths = _getList("paths", (pathNode) {
       _validate(pathNode, "Paths must be strings.", (value) => value is String);
@@ -281,8 +288,7 @@
   }
 
   /// Asserts that [field] is an int and returns its value.
-  int _getInt(String field) =>
-      _getValue(field, "int", (value) => value is int);
+  int _getInt(String field) => _getValue(field, "int", (value) => value is int);
 
   /// Asserts that [field] is a boolean and returns its value.
   bool _getBool(String field) =>
@@ -296,7 +302,8 @@
   /// contains.
   ///
   /// Returns a list of values returned by [forElement].
-  List/*<T>*/ _getList/*<T>*/(String field,
+  List/*<T>*/ _getList/*<T>*/(
+      String field,
       /*=T*/ forElement(YamlNode elementNode)) {
     var node = _getNode(field, "list", (value) => value is List) as YamlList;
     if (node == null) return [];
@@ -307,14 +314,15 @@
   ///
   /// Returns a map with the keys and values returned by [key] and [value]. Each
   /// of these defaults to asserting that the value is a string.
-  Map/*<K, V>*/ _getMap/*<K, V>*/(String field, {/*=K*/ key(YamlNode keyNode),
+  Map/*<K, V>*/ _getMap/*<K, V>*/(String field,
+      {/*=K*/ key(YamlNode keyNode),
       /*=V*/ value(YamlNode valueNode)}) {
     var node = _getNode(field, "map", (value) => value is Map) as YamlMap;
     if (node == null) return {};
 
     key ??= (keyNode) {
-      _validate(keyNode, "$field keys must be strings.",
-          (value) => value is String);
+      _validate(
+          keyNode, "$field keys must be strings.", (value) => value is String);
 
       return keyNode.value as dynamic/*=K*/;
     };
@@ -335,9 +343,7 @@
   /// and returns it
   String _parseIdentifierLike(YamlNode node, String name) {
     _validate(node, "$name must be a string.", (value) => value is String);
-    _validate(
-        node,
-        "$name must be an (optionally hyphenated) Dart identifier.",
+    _validate(node, "$name must be an (optionally hyphenated) Dart identifier.",
         (value) => value.contains(anchoredHyphenatedIdentifier));
     return node.value;
   }
@@ -351,7 +357,9 @@
   ///
   /// If [parse] throws a [FormatException], it's wrapped to include [node]'s
   /// span.
-  /*=T*/ _parseNode/*<T>*/(YamlNode node, String name,
+  /*=T*/ _parseNode/*<T>*/(
+      YamlNode node,
+      String name,
       /*=T*/ parse(String value)) {
     _validate(node, "$name must be a string.", (value) => value is String);
 
@@ -379,14 +387,12 @@
   /// [name] is the name of the field, which is used for error-handling.
   /// [runnerConfig] controls whether runner configuration is allowed in the
   /// nested configuration. It defaults to [_runnerConfig].
-  Configuration _nestedConfig(YamlNode node, String name,
-      {bool runnerConfig}) {
+  Configuration _nestedConfig(YamlNode node, String name, {bool runnerConfig}) {
     if (node == null || node.value == null) return Configuration.empty;
 
     _validate(node, "$name must be a map.", (value) => value is Map);
     var loader = new _ConfigurationLoader(node, _source,
-        global: _global,
-        runnerConfig: runnerConfig ?? _runnerConfig);
+        global: _global, runnerConfig: runnerConfig ?? _runnerConfig);
     return loader.load();
   }
 
@@ -399,13 +405,12 @@
   /// logic into a parent [Configuration], leaving only maps to
   /// [SuiteConfiguration]s. The [create] function is used to construct
   /// [Configuration]s from the resolved maps.
-  Configuration _extractPresets/*<T>*/(
-      Map/*<T, Configuration>*/ map,
+  Configuration _extractPresets/*<T>*/(Map/*<T, Configuration>*/ map,
       Configuration create(Map/*<T, SuiteConfiguration>*/ map)) {
     if (map.isEmpty) return Configuration.empty;
 
-    var base = /*<T, SuiteConfiguration>*/{};
-    var presets = /*<String, Map<T, SuiteConfiguration>>*/{};
+    var base = /*<T, SuiteConfiguration>*/ {};
+    var presets = /*<String, Map<T, SuiteConfiguration>>*/ {};
     map.forEach((key, config) {
       base[key] = config.suiteDefaults;
       config.presets.forEach((preset, presetConfig) {
diff --git a/pub/test/lib/src/runner/configuration/reporters.dart b/pub/test/lib/src/runner/configuration/reporters.dart
new file mode 100644
index 0000000..50b7112
--- /dev/null
+++ b/pub/test/lib/src/runner/configuration/reporters.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+import 'dart:io';
+
+import '../../util/io.dart';
+import '../configuration.dart';
+import '../engine.dart';
+import '../reporter.dart';
+import '../reporter/compact.dart';
+import '../reporter/expanded.dart';
+import '../reporter/json.dart';
+
+/// Constructs a reporter for the provided engine with the provided
+/// configuration.
+typedef Reporter ReporterFactory(Configuration configuration, Engine engine);
+
+/// Container for a reporter description and corresponding factory.
+class ReporterDetails {
+  final String description;
+  final ReporterFactory factory;
+  ReporterDetails(this.description, this.factory);
+}
+
+/// All reporters and their corresponding details.
+final UnmodifiableMapView<String, ReporterDetails> allReporters =
+    new UnmodifiableMapView<String, ReporterDetails>(_allReporters);
+
+final _allReporters = <String, ReporterDetails>{
+  "expanded": new ReporterDetails(
+      "A separate line for each update.",
+      (config, engine) => ExpandedReporter.watch(engine,
+          color: config.color,
+          printPath: config.paths.length > 1 ||
+              new Directory(config.paths.single).existsSync(),
+          printPlatform: config.suiteDefaults.platforms.length > 1)),
+  "compact": new ReporterDetails("A single line, updated continuously.",
+      (_, engine) => CompactReporter.watch(engine)),
+  "json": new ReporterDetails(
+      "A machine-readable format (see https://goo.gl/gBsV1a).",
+      (_, engine) => JsonReporter.watch(engine)),
+};
+
+final defaultReporter =
+    inTestTests ? 'expanded' : (Platform.isWindows ? 'expanded' : 'compact');
+
+/// **Do not call this function without express permission from the test package
+/// authors**.
+///
+/// This globally registers a reporter.
+void registerReporter(String name, ReporterDetails reporterDetails) {
+  _allReporters[name] = reporterDetails;
+}
diff --git a/pub/test/lib/src/runner/configuration/suite.dart b/pub/test/lib/src/runner/configuration/suite.dart
index 3afaf46..d4541e8 100644
--- a/pub/test/lib/src/runner/configuration/suite.dart
+++ b/pub/test/lib/src/runner/configuration/suite.dart
@@ -86,6 +86,7 @@
         forTag: mapMap(tags, value: (_, config) => config.metadata),
         onPlatform: mapMap(onPlatform, value: (_, config) => config.metadata));
   }
+
   final Metadata _metadata;
 
   /// The set of tags that have been declared in any way in this configuration.
@@ -107,6 +108,7 @@
     _knownTags = new UnmodifiableSetView(known);
     return _knownTags;
   }
+
   Set<String> _knownTags;
 
   /// All child configurations of [this] that may be selected under various
@@ -116,8 +118,8 @@
     yield* onPlatform.values;
   }
 
-  factory SuiteConfiguration({
-      bool jsTrace,
+  factory SuiteConfiguration(
+      {bool jsTrace,
       bool runSkipped,
       Iterable<String> dart2jsArgs,
       String precompiledPath,
@@ -131,6 +133,7 @@
       // Test-level configuration
       Timeout timeout,
       bool verboseTrace,
+      bool chainStackTraces,
       bool skip,
       String skipReason,
       PlatformSelector testOn,
@@ -149,6 +152,7 @@
         metadata: new Metadata(
             timeout: timeout,
             verboseTrace: verboseTrace,
+            chainStackTraces: chainStackTraces,
             skip: skip,
             skipReason: skipReason,
             testOn: testOn,
@@ -160,18 +164,18 @@
   ///
   /// Unlike [new SuiteConfiguration], this assumes [tags] is already
   /// resolved.
-  SuiteConfiguration._({
-          bool jsTrace,
-          bool runSkipped,
-          Iterable<String> dart2jsArgs,
-          this.precompiledPath,
-          Iterable<Pattern> patterns,
-          Iterable<TestPlatform> platforms,
-          BooleanSelector includeTags,
-          BooleanSelector excludeTags,
-          Map<BooleanSelector, SuiteConfiguration> tags,
-          Map<PlatformSelector, SuiteConfiguration> onPlatform,
-          Metadata metadata})
+  SuiteConfiguration._(
+      {bool jsTrace,
+      bool runSkipped,
+      Iterable<String> dart2jsArgs,
+      this.precompiledPath,
+      Iterable<Pattern> patterns,
+      Iterable<TestPlatform> platforms,
+      BooleanSelector includeTags,
+      BooleanSelector excludeTags,
+      Map<BooleanSelector, SuiteConfiguration> tags,
+      Map<PlatformSelector, SuiteConfiguration> onPlatform,
+      Metadata metadata})
       : _jsTrace = jsTrace,
         _runSkipped = runSkipped,
         dart2jsArgs = _list(dart2jsArgs) ?? const [],
@@ -198,7 +202,7 @@
   /// If [input] is `null` or empty, this returns `null`.
   static List/*<T>*/ _list/*<T>*/(Iterable/*<T>*/ input) {
     if (input == null) return null;
-    var list = new List/*<T>*/.unmodifiable(input);
+    var list = new List/*<T>*/ .unmodifiable(input);
     if (list.isEmpty) return null;
     return list;
   }
@@ -237,8 +241,8 @@
   ///
   /// Note that unlike [merge], this has no merging behavior—the old value is
   /// always replaced by the new one.
-  SuiteConfiguration change({
-      bool jsTrace,
+  SuiteConfiguration change(
+      {bool jsTrace,
       bool runSkipped,
       Iterable<String> dart2jsArgs,
       String precompiledPath,
@@ -252,6 +256,7 @@
       // Test-level configuration
       Timeout timeout,
       bool verboseTrace,
+      bool chainStackTraces,
       bool skip,
       String skipReason,
       PlatformSelector testOn,
@@ -270,6 +275,7 @@
         metadata: _metadata.change(
             timeout: timeout,
             verboseTrace: verboseTrace,
+            chainStackTraces: chainStackTraces,
             skip: skip,
             skipReason: skipReason,
             testOn: testOn,
diff --git a/pub/test/lib/src/runner/configuration/values.dart b/pub/test/lib/src/runner/configuration/values.dart
index b136862..6108c9c 100644
--- a/pub/test/lib/src/runner/configuration/values.dart
+++ b/pub/test/lib/src/runner/configuration/values.dart
@@ -7,22 +7,12 @@
 
 import 'package:glob/glob.dart';
 
-import '../../util/io.dart';
-
 /// The default number of test suites to run at once.
 ///
 /// This defaults to half the available processors, since presumably some of
 /// them will be used for the OS and other processes.
 final defaultConcurrency = math.max(1, Platform.numberOfProcessors ~/ 2);
 
-/// The reporters supported by the test runner.
-const allReporters = const ["compact", "expanded", "json"];
-
-/// The default reporter.
-final defaultReporter = inTestTests
-    ? 'expanded'
-    : (Platform.isWindows ? 'expanded' : 'compact');
-
 /// The default filename pattern.
 ///
 /// This is stored here so that we don't have to recompile it multiple times.
diff --git a/pub/test/lib/src/runner/console.dart b/pub/test/lib/src/runner/console.dart
index ba2bcf4..6150474 100644
--- a/pub/test/lib/src/runner/console.dart
+++ b/pub/test/lib/src/runner/console.dart
@@ -73,7 +73,7 @@
         if (command == null) {
           stderr.writeln(
               "${_red}Unknown command $_bold$commandName$_noColor$_red."
-                "$_noColor");
+              "$_noColor");
         } else {
           await command.body();
         }
@@ -92,9 +92,8 @@
 
   /// Displays the help info for the console commands.
   void _displayHelp() {
-    var maxCommandLength = _commands.values
-        .map((command) => command.name.length)
-        .reduce(math.max);
+    var maxCommandLength =
+        _commands.values.map((command) => command.name.length).reduce(math.max);
 
     for (var command in _commands.values) {
       var name = command.name.padRight(maxCommandLength + 4);
diff --git a/pub/test/lib/src/runner/debugger.dart b/pub/test/lib/src/runner/debugger.dart
index 5a3f6f0..e26c5a7 100644
--- a/pub/test/lib/src/runner/debugger.dart
+++ b/pub/test/lib/src/runner/debugger.dart
@@ -24,8 +24,8 @@
 /// Returns a [CancelableOperation] that will complete once the suite has
 /// finished running. If the operation is canceled, the debugger will clean up
 /// any resources it allocated.
-CancelableOperation debug(Engine engine, Reporter reporter,
-    LoadSuite loadSuite) {
+CancelableOperation debug(
+    Engine engine, Reporter reporter, LoadSuite loadSuite) {
   var debugger;
   var canceled = false;
   return new CancelableOperation.fromFuture(() async {
@@ -85,9 +85,8 @@
 
   _Debugger(this._engine, this._reporter, this._suite)
       : _console = new Console(color: Configuration.current.color) {
-    _console.registerCommand(
-        "restart", "Restart the current test after it finishes running.",
-        _restartTest);
+    _console.registerCommand("restart",
+        "Restart the current test after it finishes running.", _restartTest);
 
     _onDebuggingSubscription = _suite.onDebugging.listen((debugging) {
       if (debugging) {
@@ -152,8 +151,8 @@
           }
         }
 
-        var buffer = new StringBuffer(
-            "${bold}The test runner is paused.${noColor} ");
+        var buffer =
+            new StringBuffer("${bold}The test runner is paused.${noColor} ");
         if (!_suite.platform.isHeadless) {
           buffer.write("Open the dev console in ${_suite.platform} ");
         } else {
@@ -167,10 +166,9 @@
         print(wordWrap(buffer.toString()));
       }
 
-      await inCompletionOrder([
-        _suite.environment.displayPause(),
-        cancelableNext(stdinLines)
-      ]).first;
+      await inCompletionOrder(
+              [_suite.environment.displayPause(), cancelableNext(stdinLines)])
+          .first;
     } finally {
       if (!_json) _reporter.resume();
     }
diff --git a/pub/test/lib/src/runner/engine.dart b/pub/test/lib/src/runner/engine.dart
index 7173444..4fda5b4 100644
--- a/pub/test/lib/src/runner/engine.dart
+++ b/pub/test/lib/src/runner/engine.dart
@@ -81,9 +81,8 @@
   /// A future that completes once [this] is unpaused.
   ///
   /// If [this] isn't paused, this completes immediately.
-  Future get _onUnpaused => _pauseCompleter == null
-      ? new Future.value()
-      : _pauseCompleter.future;
+  Future get _onUnpaused =>
+      _pauseCompleter == null ? new Future.value() : _pauseCompleter.future;
 
   /// Whether all tests passed or were skipped.
   ///
@@ -91,7 +90,8 @@
   /// This will be `null` if [close] was called before all the tests finished
   /// running.
   Future<bool> get success async {
-    await Future.wait([_group.future, _loadPool.done], eagerError: true);
+    await Future
+        .wait(<Future>[_group.future, _loadPool.done], eagerError: true);
     if (_closedBeforeDone) return null;
     return liveTests.every((liveTest) => liveTest.state.result.isPassing);
   }
@@ -158,9 +158,9 @@
   /// [skipped], [failed], and [active].
   ///
   /// [LiveTest.run] must not be called on these tests.
-  Set<LiveTest> get liveTests => new UnionSet.from(
-      [passed, skipped, failed, new IterableSet(active)],
-      disjoint: true);
+  Set<LiveTest> get liveTests =>
+      new UnionSet.from([passed, skipped, failed, new IterableSet(active)],
+          disjoint: true);
 
   /// A stream that emits each [LiveTest] as it's about to start running.
   ///
@@ -301,8 +301,8 @@
       var skipGroup = !suiteConfig.runSkipped && group.metadata.skip;
       var setUpAllSucceeded = true;
       if (!skipGroup && group.setUpAll != null) {
-        var liveTest = group.setUpAll.load(suiteController.liveSuite.suite,
-            groups: parents);
+        var liveTest = group.setUpAll
+            .load(suiteController.liveSuite.suite, groups: parents);
         await _runLiveTest(suiteController, liveTest, countSuccess: false);
         setUpAllSucceeded = liveTest.state.result.isPassing;
       }
@@ -317,8 +317,7 @@
             await _runSkippedTest(suiteController, entry, parents);
           } else {
             var test = entry as Test;
-            await _runLiveTest(
-                suiteController,
+            await _runLiveTest(suiteController,
                 test.load(suiteController.liveSuite.suite, groups: parents));
           }
         }
@@ -327,8 +326,8 @@
       // Even if we're closed or setUpAll failed, we want to run all the
       // teardowns to ensure that any state is properly cleaned up.
       if (!skipGroup && group.tearDownAll != null) {
-        var liveTest = group.tearDownAll.load(suiteController.liveSuite.suite,
-            groups: parents);
+        var liveTest = group.tearDownAll
+            .load(suiteController.liveSuite.suite, groups: parents);
         await _runLiveTest(suiteController, liveTest, countSuccess: false);
         if (_closed) await liveTest.close();
       }
@@ -388,18 +387,18 @@
   Future _runSkippedTest(LiveSuiteController suiteController, Test test,
       List<Group> parents) async {
     await _onUnpaused;
-    var skipped = new LocalTest(test.name, test.metadata, () {},
-        trace: test.trace);
+    var skipped =
+        new LocalTest(test.name, test.metadata, () {}, trace: test.trace);
 
     var controller;
-    controller = new LiveTestController(
-        suiteController.liveSuite.suite, skipped, () {
+    controller =
+        new LiveTestController(suiteController.liveSuite.suite, skipped, () {
       controller.setState(const State(Status.running, Result.success));
       controller.setState(const State(Status.running, Result.skipped));
 
       if (skipped.metadata.skipReason != null) {
-        controller.message(
-            new Message.skip("Skip: ${skipped.metadata.skipReason}"));
+        controller
+            .message(new Message.skip("Skip: ${skipped.metadata.skipReason}"));
       }
 
       controller.setState(const State(Status.complete, Result.skipped));
diff --git a/pub/test/lib/src/runner/hybrid_listener.dart b/pub/test/lib/src/runner/hybrid_listener.dart
index df3b75d..a8f1678 100644
--- a/pub/test/lib/src/runner/hybrid_listener.dart
+++ b/pub/test/lib/src/runner/hybrid_listener.dart
@@ -14,16 +14,14 @@
 
 /// A sink transformer that wraps data and error events so that errors can be
 /// decoded after being JSON-serialized.
-final _transformer = new StreamSinkTransformer.fromHandlers(
-    handleData: (data, sink) {
-      ensureJsonEncodable(data);
-      sink.add({"type": "data", "data": data});
-    }, handleError: (error, stackTrace, sink) {
-      sink.add({
-        "type": "error",
-        "error": RemoteException.serialize(error, stackTrace)
-      });
-    });
+final _transformer =
+    new StreamSinkTransformer.fromHandlers(handleData: (data, sink) {
+  ensureJsonEncodable(data);
+  sink.add({"type": "data", "data": data});
+}, handleError: (error, stackTrace, sink) {
+  sink.add(
+      {"type": "error", "error": RemoteException.serialize(error, stackTrace)});
+});
 
 /// Runs the body of a hybrid isolate and communicates its messages, errors, and
 /// prints to the main isolate.
diff --git a/pub/test/lib/src/runner/live_suite_controller.dart b/pub/test/lib/src/runner/live_suite_controller.dart
index a7d1768..ae5a933 100644
--- a/pub/test/lib/src/runner/live_suite_controller.dart
+++ b/pub/test/lib/src/runner/live_suite_controller.dart
@@ -7,8 +7,8 @@
 import 'package:async/async.dart' hide Result;
 import 'package:collection/collection.dart';
 
-import '../backend/state.dart';
 import '../backend/live_test.dart';
+import '../backend/state.dart';
 import 'live_suite.dart';
 import 'runner_suite.dart';
 
@@ -145,11 +145,11 @@
 
   /// Closes the underlying suite.
   Future close() => _closeMemo.runOnce(() async {
-    try {
-      await _suite.close();
-    } finally {
-      _onCloseCompleter.complete();
-    }
-  });
+        try {
+          await _suite.close();
+        } finally {
+          _onCloseCompleter.complete();
+        }
+      });
   final _closeMemo = new AsyncMemoizer();
 }
diff --git a/pub/test/lib/src/runner/load_exception.dart b/pub/test/lib/src/runner/load_exception.dart
index d9cfc20..a3f3af4 100644
--- a/pub/test/lib/src/runner/load_exception.dart
+++ b/pub/test/lib/src/runner/load_exception.dart
@@ -52,9 +52,10 @@
 
       innerString = innerString.replaceFirst("FileSystemException: ", "");
       innerString = innerString.split("Stack Trace:\n").first.trim();
-    } if (innerError is SourceSpanException) {
-      innerString = innerError.toString(color: color)
-          .replaceFirst(" of $path", "");
+    }
+    if (innerError is SourceSpanException) {
+      innerString =
+          innerError.toString(color: color).replaceFirst(" of $path", "");
     }
 
     buffer.write(innerString.contains("\n") ? "\n" : " ");
diff --git a/pub/test/lib/src/runner/load_suite.dart b/pub/test/lib/src/runner/load_suite.dart
index 7034de4..70bbc80 100644
--- a/pub/test/lib/src/runner/load_suite.dart
+++ b/pub/test/lib/src/runner/load_suite.dart
@@ -66,7 +66,8 @@
   ///
   /// If the the load test is closed before [body] is complete, it will close
   /// the suite returned by [body] once it completes.
-  factory LoadSuite(String name, SuiteConfiguration config, body(),
+  factory LoadSuite(
+      String name, SuiteConfiguration config, FutureOr<RunnerSuite> body(),
       {String path, TestPlatform platform}) {
     var completer = new Completer<Pair<RunnerSuite, Zone>>.sync();
     return new LoadSuite._(name, config, () {
@@ -79,12 +80,12 @@
           if (completer.isCompleted) {
             // If the load test has already been closed, close the suite it
             // generated.
-            suite.close();
+            suite?.close();
             return;
           }
 
-          completer.complete(
-              suite == null ? null : new Pair(suite, Zone.current));
+          completer
+              .complete(suite == null ? null : new Pair(suite, Zone.current));
           invoker.removeOutstandingCallback();
         } catch (error, stackTrace) {
           registerException(error, stackTrace);
@@ -105,9 +106,9 @@
   /// A utility constructor for a load suite that just throws [exception].
   ///
   /// The suite's name will be based on [exception]'s path.
-  factory LoadSuite.forLoadException(LoadException exception,
-      SuiteConfiguration config, {StackTrace stackTrace,
-      TestPlatform platform}) {
+  factory LoadSuite.forLoadException(
+      LoadException exception, SuiteConfiguration config,
+      {StackTrace stackTrace, TestPlatform platform}) {
     if (stackTrace == null) stackTrace = new Trace.current();
 
     return new LoadSuite(
@@ -125,12 +126,16 @@
   }
 
   LoadSuite._(String name, this.config, void body(), this._suiteAndZone,
-          {String path, TestPlatform platform})
-      : super(new Group.root([
-        new LocalTest(name,
-            new Metadata(timeout: new Timeout(new Duration(minutes: 5))),
-            body)
-      ]), path: path, platform: platform);
+      {String path, TestPlatform platform})
+      : super(
+            new Group.root([
+              new LocalTest(
+                  name,
+                  new Metadata(timeout: new Timeout(new Duration(minutes: 5))),
+                  body)
+            ]),
+            path: path,
+            platform: platform);
 
   /// A constructor used by [changeSuite].
   LoadSuite._changeSuite(LoadSuite old, this._suiteAndZone)
diff --git a/pub/test/lib/src/runner/loader.dart b/pub/test/lib/src/runner/loader.dart
index f24ddd0..194b78a 100644
--- a/pub/test/lib/src/runner/loader.dart
+++ b/pub/test/lib/src/runner/loader.dart
@@ -90,8 +90,8 @@
   /// This emits [LoadSuite]s that must then be run to emit the actual
   /// [RunnerSuite]s defined in the file.
   Stream<LoadSuite> loadDir(String dir, SuiteConfiguration suiteConfig) {
-    return StreamGroup.merge(new Directory(dir).listSync(recursive: true)
-        .map((entry) {
+    return StreamGroup
+        .merge(new Directory(dir).listSync(recursive: true).map((entry) {
       if (entry is! File) return new Stream.fromIterable([]);
 
       if (!_config.filename.matches(p.basename(entry.path))) {
@@ -99,7 +99,7 @@
       }
 
       if (p.split(entry.path).contains('packages')) {
-         return new Stream.fromIterable([]);
+        return new Stream.fromIterable([]);
       }
 
       return loadFile(entry.path, suiteConfig);
@@ -112,17 +112,18 @@
   /// [RunnerSuite]s defined in the file.
   ///
   /// This will emit a [LoadException] if the file fails to load.
-  Stream<LoadSuite> loadFile(String path, SuiteConfiguration suiteConfig)
-      async* {
+  Stream<LoadSuite> loadFile(
+      String path, SuiteConfiguration suiteConfig) async* {
     try {
-      suiteConfig = suiteConfig.merge(
-          new SuiteConfiguration.fromMetadata(parseMetadata(path)));
+      suiteConfig = suiteConfig
+          .merge(new SuiteConfiguration.fromMetadata(parseMetadata(path)));
     } on AnalyzerErrorGroup catch (_) {
       // Ignore the analyzer's error, since its formatting is much worse than
       // the VM's or dart2js's.
     } on FormatException catch (error, stackTrace) {
       yield new LoadSuite.forLoadException(
-          new LoadException(path, error), suiteConfig, stackTrace: stackTrace);
+          new LoadException(path, error), suiteConfig,
+          stackTrace: stackTrace);
       return;
     }
 
@@ -149,7 +150,8 @@
             new Group.root(
                 [new LocalTest("(suite)", platformConfig.metadata, () {})],
                 metadata: platformConfig.metadata),
-            path: path, platform: platform));
+            path: path,
+            platform: platform));
         continue;
       }
 
@@ -160,11 +162,12 @@
         try {
           var plugin = await memo.runOnce(_platformCallbacks[platform]);
           var suite = await plugin.load(path, platform, platformConfig);
-          _suites.add(suite);
+          if (suite != null) _suites.add(suite);
           return suite;
         } catch (error, stackTrace) {
           if (error is LoadException) rethrow;
           await new Future.error(new LoadException(path, error), stackTrace);
+          return null;
         }
       }, path: path, platform: platform);
     }
@@ -179,17 +182,17 @@
 
   /// Closes the loader and releases all resources allocated by it.
   Future close() => _closeMemo.runOnce(() async {
-    await Future.wait([
-      Future.wait(_platformPlugins.values.map((memo) async {
-        if (!memo.hasRun) return;
-        await (await memo.future).close();
-      })),
-      Future.wait(_suites.map((suite) => suite.close()))
-    ]);
+        await Future.wait([
+          Future.wait(_platformPlugins.values.map((memo) async {
+            if (!memo.hasRun) return;
+            await (await memo.future).close();
+          })),
+          Future.wait(_suites.map((suite) => suite.close()))
+        ]);
 
-    _platformPlugins.clear();
-    _platformCallbacks.clear();
-    _suites.clear();
-  });
+        _platformPlugins.clear();
+        _platformCallbacks.clear();
+        _suites.clear();
+      });
   final _closeMemo = new AsyncMemoizer();
 }
diff --git a/pub/test/lib/src/runner/parse_metadata.dart b/pub/test/lib/src/runner/parse_metadata.dart
index 7617c50..7b86166 100644
--- a/pub/test/lib/src/runner/parse_metadata.dart
+++ b/pub/test/lib/src/runner/parse_metadata.dart
@@ -33,22 +33,24 @@
   /// All prefixes defined by imports in this file.
   Set<String> _prefixes;
 
-  _Parser(String path)
-      : _path = path {
+  _Parser(String path) : _path = path {
     var contents = new File(path).readAsStringSync();
     var directives = parseDirectives(contents, name: path).directives;
     _annotations = directives.isEmpty ? [] : directives.first.metadata;
 
     // We explicitly *don't* just look for "package:test" imports here,
     // because it could be re-exported from another library.
-    _prefixes = directives.map((directive) {
-      if (directive is ImportDirective) {
-        if (directive.prefix == null) return null;
-        return directive.prefix.name;
-      } else {
-        return null;
-      }
-    }).where((prefix) => prefix != null).toSet();
+    _prefixes = directives
+        .map((directive) {
+          if (directive is ImportDirective) {
+            if (directive.prefix == null) return null;
+            return directive.prefix.name;
+          } else {
+            return null;
+          }
+        })
+        .where((prefix) => prefix != null)
+        .toSet();
   }
 
   /// Parses the metadata.
@@ -60,8 +62,8 @@
     Set<String> tags;
 
     for (var annotation in _annotations) {
-      var pair = _resolveConstructor(
-          annotation.name, annotation.constructorName);
+      var pair =
+          _resolveConstructor(annotation.name, annotation.constructorName);
       var name = pair.first;
       var constructorName = pair.last;
 
@@ -100,8 +102,8 @@
     _assertConstructorName(constructorName, 'TestOn', annotation);
     _assertArguments(annotation.arguments, 'TestOn', annotation, positional: 1);
     var literal = _parseString(annotation.arguments.arguments.first);
-    return _contextualize(literal,
-        () => new PlatformSelector.parse(literal.stringValue));
+    return _contextualize(
+        literal, () => new PlatformSelector.parse(literal.stringValue));
   }
 
   /// Parses a `@Timeout` annotation.
@@ -113,7 +115,7 @@
         validNames: [null, 'factor', 'none']);
 
     var description = 'Timeout';
-    if (constructorName != null) description += '.$constructorName'; 
+    if (constructorName != null) description += '.$constructorName';
 
     if (constructorName == 'none') {
       _assertNoArguments(annotation, description);
@@ -130,8 +132,8 @@
 
   /// Parses a `Timeout` constructor.
   Timeout _parseTimeoutConstructor(InstanceCreationExpression constructor) {
-    var name = _parseConstructor(constructor, 'Timeout',
-        validNames: [null, 'factor']);
+    var name =
+        _parseConstructor(constructor, 'Timeout', validNames: [null, 'factor']);
 
     var description = 'Timeout';
     if (name != null) description += '.$name';
@@ -178,13 +180,14 @@
     _assertConstructorName(constructorName, 'Tags', annotation);
     _assertArguments(annotation.arguments, 'Tags', annotation, positional: 1);
 
-    return _parseList(annotation.arguments.arguments.first).map((tagExpression) {
+    return _parseList(annotation.arguments.arguments.first)
+        .map((tagExpression) {
       var name = _parseString(tagExpression).stringValue;
       if (name.contains(anchoredHyphenatedIdentifier)) return name;
 
       throw new SourceSpanFormatException(
           "Invalid tag name. Tags must be (optionally hyphenated) Dart "
-            "identifiers.",
+          "identifiers.",
           _spanFor(tagExpression));
     }).toSet();
   }
@@ -193,27 +196,26 @@
   ///
   /// [annotation] is the annotation. [constructorName] is the name of the named
   /// constructor for the annotation, if any.
-  Map<PlatformSelector, Metadata> _parseOnPlatform(Annotation annotation,
-      String constructorName) {
+  Map<PlatformSelector, Metadata> _parseOnPlatform(
+      Annotation annotation, String constructorName) {
     _assertConstructorName(constructorName, 'OnPlatform', annotation);
     _assertArguments(annotation.arguments, 'OnPlatform', annotation,
         positional: 1);
 
     return _parseMap(annotation.arguments.arguments.first, key: (key) {
       var selector = _parseString(key);
-      return _contextualize(selector,
-          () => new PlatformSelector.parse(selector.stringValue));
+      return _contextualize(
+          selector, () => new PlatformSelector.parse(selector.stringValue));
     }, value: (value) {
       var expressions = [];
       if (value is ListLiteral) {
         expressions = _parseList(value);
       } else if (value is InstanceCreationExpression ||
-                 value is PrefixedIdentifier) {
+          value is PrefixedIdentifier) {
         expressions = [value];
       } else {
         throw new SourceSpanFormatException(
-            'Expected a Timeout, Skip, or List of those.',
-            _spanFor(value));
+            'Expected a Timeout, Skip, or List of those.', _spanFor(value));
       }
 
       var timeout;
@@ -221,8 +223,9 @@
       for (var expression in expressions) {
         if (expression is InstanceCreationExpression) {
           var className = _resolveConstructor(
-              expression.constructorName.type.name,
-              expression.constructorName.name).first;
+                  expression.constructorName.type.name,
+                  expression.constructorName.name)
+              .first;
 
           if (className == 'Timeout') {
             _assertSingle(timeout, 'Timeout', expression);
@@ -246,8 +249,7 @@
         }
 
         throw new SourceSpanFormatException(
-            'Expected a Timeout or Skip.',
-            _spanFor(expression));
+            'Expected a Timeout or Skip.', _spanFor(expression));
       }
 
       return new Metadata.parse(timeout: timeout, skip: skip);
@@ -261,18 +263,24 @@
     var constructor = expression as InstanceCreationExpression;
     var valueExpressions = _assertArguments(
         constructor.argumentList, 'Duration', constructor, named: [
-      'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds'
+      'days',
+      'hours',
+      'minutes',
+      'seconds',
+      'milliseconds',
+      'microseconds'
     ]);
 
-    var values = mapMap(valueExpressions,
-        value: (_, value) => _parseInt(value));
+    var values =
+        mapMap(valueExpressions, value: (_, value) => _parseInt(value));
 
     return new Duration(
         days: values["days"] == null ? 0 : values["days"],
         hours: values["hours"] == null ? 0 : values["hours"],
         minutes: values["minutes"] == null ? 0 : values["minutes"],
         seconds: values["seconds"] == null ? 0 : values["seconds"],
-        milliseconds: values["milliseconds"] == null ? 0 : values["milliseconds"],
+        milliseconds:
+            values["milliseconds"] == null ? 0 : values["milliseconds"],
         microseconds:
             values["microseconds"] == null ? 0 : values["microseconds"]);
   }
@@ -292,8 +300,8 @@
   ///
   /// Since the parsed file isn't fully resolved, this is necessary to
   /// disambiguate between prefixed names and named constructors.
-  Pair<String, String> _resolveConstructor(Identifier identifier,
-      SimpleIdentifier constructorName) {
+  Pair<String, String> _resolveConstructor(
+      Identifier identifier, SimpleIdentifier constructorName) {
     // The syntax is ambiguous between named constructors and prefixed
     // annotations, so we need to resolve that ambiguity using the known
     // prefixes. The analyzer parses "new x.y()" as prefix "x", annotation "y",
@@ -322,15 +330,15 @@
   /// AST node for that class. [validNames], if passed, is the set of valid
   /// constructor names; if an unnamed constructor is valid, it should include
   /// `null`. By default, only an unnamed constructor is allowed.
-  void _assertConstructorName(String constructorName, String nodeName,
-      AstNode node, {Iterable<String> validNames}) {
+  void _assertConstructorName(
+      String constructorName, String nodeName, AstNode node,
+      {Iterable<String> validNames}) {
     if (validNames == null) validNames = [null];
     if (validNames.contains(constructorName)) return;
 
     if (constructorName == null) {
       throw new SourceSpanFormatException(
-          "$nodeName doesn't have an unnamed constructor.",
-          _spanFor(node));
+          "$nodeName doesn't have an unnamed constructor.", _spanFor(node));
     } else {
       throw new SourceSpanFormatException(
           '$nodeName doesn\'t have a constructor named "$constructorName".',
@@ -355,8 +363,7 @@
     }
 
     var constructor = expression as InstanceCreationExpression;
-    var pair = _resolveConstructor(
-        constructor.constructorName.type.name,
+    var pair = _resolveConstructor(constructor.constructorName.type.name,
         constructor.constructorName.name);
     var actualClassName = pair.first;
     var constructorName = pair.last;
@@ -384,8 +391,9 @@
   /// names.
   ///
   /// The set of parsed named arguments is returned.
-  Map<String, Expression> _assertArguments(ArgumentList arguments, String name,
-      AstNode node, {int positional, int optional, Iterable<String> named}) {
+  Map<String, Expression> _assertArguments(
+      ArgumentList arguments, String name, AstNode node,
+      {int positional, int optional, Iterable<String> named}) {
     if (positional == null) positional = 0;
     if (optional == null) optional = 0;
     if (named == null) named = new Set();
@@ -399,7 +407,7 @@
         .where((arg) => arg is NamedExpression)
         .map((arg) => arg as NamedExpression)
         .toList();
-    if (!actualNamed.isEmpty && named.isEmpty) {
+    if (actualNamed.isNotEmpty && named.isEmpty) {
       throw new SourceSpanFormatException(
           "$name doesn't take named arguments.", _spanFor(actualNamed.first));
     }
@@ -434,7 +442,7 @@
     if (actualPositional > positional + optional) {
       if (optional + positional == 0) {
         var buffer = new StringBuffer("$name doesn't take ");
-        if (!named.isEmpty) buffer.write("positional ");
+        if (named.isNotEmpty) buffer.write("positional ");
         buffer.write("arguments.");
         throw new SourceSpanFormatException(
             buffer.toString(), _spanFor(arguments));
@@ -481,8 +489,7 @@
     }
 
     return new Map.fromIterable(map.entries,
-        key: (entry) => key(entry.key),
-        value: (entry) => value(entry.value));
+        key: (entry) => key(entry.key), value: (entry) => value(entry.value));
   }
 
   /// Parses a List literal.
diff --git a/pub/test/lib/src/runner/plugin/environment.dart b/pub/test/lib/src/runner/plugin/environment.dart
index bceab1b..32957fd 100644
--- a/pub/test/lib/src/runner/plugin/environment.dart
+++ b/pub/test/lib/src/runner/plugin/environment.dart
@@ -19,7 +19,6 @@
 
   Uri get remoteDebuggerUrl => null;
 
-  CancelableOperation displayPause() =>
-      throw new UnsupportedError(
-          "PluginEnvironment.displayPause is not supported.");
+  CancelableOperation displayPause() => throw new UnsupportedError(
+      "PluginEnvironment.displayPause is not supported.");
 }
diff --git a/pub/test/lib/src/runner/plugin/platform_helpers.dart b/pub/test/lib/src/runner/plugin/platform_helpers.dart
index 43bf707..5d4ec15 100644
--- a/pub/test/lib/src/runner/plugin/platform_helpers.dart
+++ b/pub/test/lib/src/runner/plugin/platform_helpers.dart
@@ -14,6 +14,7 @@
 import '../../backend/test_platform.dart';
 import '../../util/io.dart';
 import '../../util/remote_exception.dart';
+import '../application_exception.dart';
 import '../configuration.dart';
 import '../configuration/suite.dart';
 import '../environment.dart';
@@ -23,6 +24,8 @@
 
 typedef StackTrace _MapTrace(StackTrace trace);
 
+final _deserializeTimeout = new Duration(seconds: 45);
+
 /// A helper method for creating a [RunnerSuiteController] containing tests
 /// that communicate over [channel].
 ///
@@ -37,9 +40,12 @@
 /// If [asciiSymbols] is passed, it controls whether the `symbol` package is
 /// configured to use plain ASCII or Unicode symbols. It defaults to `true` on
 /// Windows and `false` elsewhere.
-Future<RunnerSuiteController> deserializeSuite(String path,
-    TestPlatform platform, SuiteConfiguration suiteConfig,
-    Environment environment, StreamChannel channel,
+Future<RunnerSuiteController> deserializeSuite(
+    String path,
+    TestPlatform platform,
+    SuiteConfiguration suiteConfig,
+    Environment environment,
+    StreamChannel channel,
     {StackTrace mapTrace(StackTrace trace)}) async {
   if (mapTrace == null) mapTrace = (trace) => trace;
 
@@ -71,42 +77,47 @@
     }
   }
 
-  suiteChannel.stream.listen((response) {
-    switch (response["type"]) {
-      case "print":
-        print(response["line"]);
-        break;
+  suiteChannel.stream.listen(
+      (response) {
+        switch (response["type"]) {
+          case "print":
+            print(response["line"]);
+            break;
 
-      case "loadException":
-        handleError(
-            new LoadException(path, response["message"]),
+          case "loadException":
+            handleError(new LoadException(path, response["message"]),
+                new Trace.current());
+            break;
+
+          case "error":
+            var asyncError = RemoteException.deserialize(response["error"]);
+            handleError(new LoadException(path, asyncError.error),
+                mapTrace(asyncError.stackTrace));
+            break;
+
+          case "success":
+            var deserializer = new _Deserializer(suiteChannel, mapTrace);
+            completer.complete(deserializer.deserializeGroup(response["root"]));
+            break;
+        }
+      },
+      onError: handleError,
+      onDone: () {
+        if (completer.isCompleted) return;
+        completer.completeError(
+            new LoadException(
+                path, "Connection closed before test suite loaded."),
             new Trace.current());
-        break;
-
-      case "error":
-        var asyncError = RemoteException.deserialize(response["error"]);
-        handleError(
-            new LoadException(path, asyncError.error),
-            mapTrace(asyncError.stackTrace));
-        break;
-
-      case "success":
-        var deserializer = new _Deserializer(suiteChannel, mapTrace);
-        completer.complete(deserializer.deserializeGroup(response["root"]));
-        break;
-    }
-  }, onError: handleError, onDone: () {
-    if (completer.isCompleted) return;
-    completer.completeError(
-        new LoadException(
-            path, "Connection closed before test suite loaded."),
-        new Trace.current());
-  });
+      });
 
   return new RunnerSuiteController(
       environment,
       suiteConfig,
-      await completer.future,
+      await completer.future.timeout(_deserializeTimeout, onTimeout: () {
+        throw new ApplicationException(
+            "Timed out while loading the test suite.\n"
+            "It's likely that there's a missing import or syntax error.");
+      }),
       path: path,
       platform: platform,
       os: currentOS,
@@ -126,11 +137,13 @@
   /// Deserializes [group] into a concrete [Group].
   Group deserializeGroup(Map group) {
     var metadata = new Metadata.deserialize(group['metadata']);
-    return new Group(group['name'], (group['entries'] as List).map((entry) {
-      var map = entry as Map;
-      if (map['type'] == 'group') return deserializeGroup(map);
-      return _deserializeTest(map);
-    }),
+    return new Group(
+        group['name'],
+        (group['entries'] as List).map((entry) {
+          var map = entry as Map;
+          if (map['type'] == 'group') return deserializeGroup(map);
+          return _deserializeTest(map);
+        }),
         metadata: metadata,
         trace: group['trace'] == null ? null : new Trace.parse(group['trace']),
         setUpAll: _deserializeTest(group['setUpAll']),
diff --git a/pub/test/lib/src/runner/remote_listener.dart b/pub/test/lib/src/runner/remote_listener.dart
index d245a97..f23695f 100644
--- a/pub/test/lib/src/runner/remote_listener.dart
+++ b/pub/test/lib/src/runner/remote_listener.dart
@@ -42,8 +42,8 @@
     // This has to be synchronous to work around sdk#25745. Otherwise, there'll
     // be an asynchronous pause before a syntax error notification is sent,
     // which will cause the send to fail entirely.
-    var controller = new StreamChannelController(
-        allowForeignErrors: false, sync: true);
+    var controller =
+        new StreamChannelController(allowForeignErrors: false, sync: true);
     var channel = new MultiChannel(controller.local);
 
     var printZone = hidePrints ? null : Zone.current;
@@ -70,16 +70,14 @@
 
       var message = await channel.stream.first;
 
-      if (message['asciiGlyphs']) glyph.ascii = true;
+      if (message['asciiGlyphs'] ?? false) glyph.ascii = true;
       var metadata = new Metadata.deserialize(message['metadata']);
       var declarer = new Declarer(
-          metadata: metadata,
-          collectTraces: message['collectTraces']);
+          metadata: metadata, collectTraces: message['collectTraces']);
       await declarer.declare(main);
 
-      var os = message['os'] == null
-          ? null
-          : OperatingSystem.find(message['os']);
+      var os =
+          message['os'] == null ? null : OperatingSystem.find(message['os']);
       var platform = TestPlatform.find(message['platform']);
       var suite = new Suite(declarer.build(),
           platform: platform, os: os, path: message['path']);
@@ -94,7 +92,6 @@
     return controller.foreign;
   }
 
-
   /// Sends a message over [channel] indicating that the tests failed to load.
   ///
   /// [message] should describe the failure.
@@ -124,8 +121,8 @@
   /// Serializes [group] into a JSON-safe map.
   ///
   /// [parents] lists the groups that contain [group].
-  Map _serializeGroup(MultiChannel channel, Group group,
-      Iterable<Group> parents) {
+  Map _serializeGroup(
+      MultiChannel channel, Group group, Iterable<Group> parents) {
     parents = parents.toList()..add(group);
     return {
       "type": "group",
@@ -152,8 +149,7 @@
     var testChannel = channel.virtualChannel();
     testChannel.stream.listen((message) {
       assert(message['command'] == 'run');
-      _runLiveTest(
-          test.load(_suite, groups: groups),
+      _runLiveTest(test.load(_suite, groups: groups),
           channel.virtualChannel(message['channel']));
     });
 
@@ -184,8 +180,8 @@
     liveTest.onError.listen((asyncError) {
       channel.sink.add({
         "type": "error",
-        "error": RemoteException.serialize(
-            asyncError.error, asyncError.stackTrace)
+        "error":
+            RemoteException.serialize(asyncError.error, asyncError.stackTrace)
       });
     });
 
diff --git a/pub/test/lib/src/runner/reporter/compact.dart b/pub/test/lib/src/runner/reporter/compact.dart
index ed0157c..a964672 100644
--- a/pub/test/lib/src/runner/reporter/compact.dart
+++ b/pub/test/lib/src/runner/reporter/compact.dart
@@ -85,6 +85,9 @@
   /// The message printed for the last progress notification.
   String _lastProgressMessage;
 
+  /// The suffix added to the last progress notification.
+  String _lastProgressSuffix;
+
   /// Whether the message printed for the last progress notification was
   /// truncated.
   bool _lastProgressTruncated;
@@ -100,8 +103,7 @@
 
   /// Watches the tests run by [engine] and prints their results to the
   /// terminal.
-  static CompactReporter watch(Engine engine) =>
-      new CompactReporter._(engine);
+  static CompactReporter watch(Engine engine) => new CompactReporter._(engine);
 
   CompactReporter._(this._engine) {
     _subscriptions.add(_engine.onTestStarted.listen(_onTestStarted));
@@ -152,6 +154,7 @@
     if (!_stopwatchStarted) {
       _stopwatchStarted = true;
       _stopwatch.start();
+
       /// Keep updating the time even when nothing else is happening.
       _subscriptions.add(new Stream.periodic(new Duration(seconds: 1))
           .listen((_) => _progressLine(_lastProgressMessage)));
@@ -167,8 +170,8 @@
     _subscriptions.add(liveTest.onStateChange
         .listen((state) => _onStateChange(liveTest, state)));
 
-    _subscriptions.add(liveTest.onError.listen((error) =>
-        _onError(liveTest, error.error, error.stackTrace)));
+    _subscriptions.add(liveTest.onError
+        .listen((error) => _onError(liveTest, error.error, error.stackTrace)));
 
     _subscriptions.add(liveTest.onMessage.listen((message) {
       _progressLine(_description(liveTest), truncate: false);
@@ -185,6 +188,10 @@
   void _onStateChange(LiveTest liveTest, State state) {
     if (state.status != Status.complete) return;
 
+    // Errors are printed in [onError]; no need to print them here as well.
+    if (state.result == Result.failure) return;
+    if (state.result == Result.error) return;
+
     // Always display the name of the oldest active test, unless testing
     // is finished in which case display the last test to complete.
     if (_engine.active.isEmpty) {
@@ -198,14 +205,15 @@
   void _onError(LiveTest liveTest, error, StackTrace stackTrace) {
     if (liveTest.state.status != Status.complete) return;
 
-    _progressLine(_description(liveTest), truncate: false);
+    _progressLine(_description(liveTest),
+        truncate: false, suffix: " $_bold$_red[E]$_noColor");
     if (!_printedNewline) print('');
     _printedNewline = true;
 
     if (error is! LoadException) {
       print(indent(error.toString()));
-      var chain = terseChain(stackTrace,
-          verbose: liveTest.test.metadata.verboseTrace);
+      var chain =
+          terseChain(stackTrace, verbose: liveTest.test.metadata.verboseTrace);
       print(indent(chain.toString()));
       return;
     }
@@ -263,8 +271,10 @@
   ///
   /// [message] goes after the progress report, and may be truncated to fit the
   /// entire line within [_lineLength]. If [color] is passed, it's used as the
-  /// color for [message].
-  bool _progressLine(String message, {String color, bool truncate: true}) {
+  /// color for [message]. If [suffix] is passed, it's added to the end of
+  /// [message].
+  bool _progressLine(String message,
+      {String color, bool truncate: true, String suffix}) {
     var elapsed = _stopwatch.elapsed.inSeconds;
 
     // Print nothing if nothing has changed since the last progress line.
@@ -272,6 +282,8 @@
         _engine.skipped.length == _lastProgressSkipped &&
         _engine.failed.length == _lastProgressFailed &&
         message == _lastProgressMessage &&
+        // Don't re-print just because a suffix was removed.
+        (suffix == null || suffix == _lastProgressSuffix) &&
         // Don't re-print just because the message became re-truncated, because
         // that doesn't add information.
         (truncate || !_lastProgressTruncated) &&
@@ -287,8 +299,10 @@
     _lastProgressFailed = _engine.failed.length;
     _lastProgressElapsed = elapsed;
     _lastProgressMessage = message;
+    _lastProgressSuffix = suffix;
     _lastProgressTruncated = truncate;
 
+    if (suffix != null) message += suffix;
     if (color == null) color = '';
     var duration = _stopwatch.elapsed;
     var buffer = new StringBuffer();
@@ -346,7 +360,8 @@
   String _description(LiveTest liveTest) {
     var name = liveTest.test.name;
 
-    if (_printPath && liveTest.suite is! LoadSuite &&
+    if (_printPath &&
+        liveTest.suite is! LoadSuite &&
         liveTest.suite.path != null) {
       name = "${liveTest.suite.path}: $name";
     }
diff --git a/pub/test/lib/src/runner/reporter/expanded.dart b/pub/test/lib/src/runner/reporter/expanded.dart
index 961fe42..912dc03 100644
--- a/pub/test/lib/src/runner/reporter/expanded.dart
+++ b/pub/test/lib/src/runner/reporter/expanded.dart
@@ -86,6 +86,9 @@
   /// The message printed for the last progress notification.
   String _lastProgressMessage;
 
+  /// The suffix added to the last progress notification.
+  String _lastProgressSuffix;
+
   /// Whether the reporter is paused.
   var _paused = false;
 
@@ -101,17 +104,14 @@
   /// won't. If [printPath] is `true`, this will print the path name as part of
   /// the test description. Likewise, if [printPlatform] is `true`, this will
   /// print the platform as part of the test description.
-  static ExpandedReporter watch(Engine engine, {bool color: true,
-      bool printPath: true, bool printPlatform: true}) {
-    return new ExpandedReporter._(
-        engine,
-        color: color,
-        printPath: printPath,
-        printPlatform: printPlatform);
+  static ExpandedReporter watch(Engine engine,
+      {bool color: true, bool printPath: true, bool printPlatform: true}) {
+    return new ExpandedReporter._(engine,
+        color: color, printPath: printPath, printPlatform: printPlatform);
   }
 
-  ExpandedReporter._(this._engine, {bool color: true, bool printPath: true,
-      bool printPlatform: true})
+  ExpandedReporter._(this._engine,
+      {bool color: true, bool printPath: true, bool printPlatform: true})
       : _printPath = printPath,
         _printPlatform = printPlatform,
         _color = color,
@@ -177,8 +177,8 @@
       _progressLine(_description(liveTest));
     }
 
-    _subscriptions.add(liveTest.onError.listen((error) =>
-        _onError(liveTest, error.error, error.stackTrace)));
+    _subscriptions.add(liveTest.onError
+        .listen((error) => _onError(liveTest, error.error, error.stackTrace)));
 
     _subscriptions.add(liveTest.onMessage.listen((message) {
       _progressLine(_description(liveTest));
@@ -203,12 +203,12 @@
   void _onError(LiveTest liveTest, error, StackTrace stackTrace) {
     if (liveTest.state.status != Status.complete) return;
 
-    _progressLine(_description(liveTest));
+    _progressLine(_description(liveTest), suffix: " $_bold$_red[E]$_noColor");
 
     if (error is! LoadException) {
       print(indent(error.toString()));
-      var chain = terseChain(stackTrace,
-          verbose: liveTest.test.metadata.verboseTrace);
+      var chain =
+          terseChain(stackTrace, verbose: liveTest.test.metadata.verboseTrace);
       print(indent(chain.toString()));
       return;
     }
@@ -248,13 +248,16 @@
   ///
   /// [message] goes after the progress report, and may be truncated to fit the
   /// entire line within [_lineLength]. If [color] is passed, it's used as the
-  /// color for [message].
-  void _progressLine(String message, {String color}) {
+  /// color for [message]. If [suffix] is passed, it's added to the end of
+  /// [message].
+  void _progressLine(String message, {String color, String suffix}) {
     // Print nothing if nothing has changed since the last progress line.
     if (_engine.passed.length == _lastProgressPassed &&
         _engine.skipped.length == _lastProgressSkipped &&
         _engine.failed.length == _lastProgressFailed &&
-        message == _lastProgressMessage) {
+        message == _lastProgressMessage &&
+        // Don't re-print just because a suffix was removed.
+        (suffix == null || suffix == _lastProgressSuffix)) {
       return;
     }
 
@@ -262,7 +265,9 @@
     _lastProgressSkipped = _engine.skipped.length;
     _lastProgressFailed = _engine.failed.length;
     _lastProgressMessage = message;
+    _lastProgressSuffix = suffix;
 
+    if (suffix != null) message += suffix;
     if (color == null) color = '';
     var duration = _stopwatch.elapsed;
     var buffer = new StringBuffer();
@@ -309,7 +314,8 @@
   String _description(LiveTest liveTest) {
     var name = liveTest.test.name;
 
-    if (_printPath && liveTest.suite is! LoadSuite &&
+    if (_printPath &&
+        liveTest.suite is! LoadSuite &&
         liveTest.suite.path != null) {
       name = "${liveTest.suite.path}: $name";
     }
diff --git a/pub/test/lib/src/runner/reporter/json.dart b/pub/test/lib/src/runner/reporter/json.dart
index 4b3d65d..374ad21 100644
--- a/pub/test/lib/src/runner/reporter/json.dart
+++ b/pub/test/lib/src/runner/reporter/json.dart
@@ -68,15 +68,10 @@
     _subscriptions.add(_engine.success.asStream().listen(_onDone));
 
     _subscriptions.add(_engine.onSuiteAdded.listen(null, onDone: () {
-      _emit("allSuites", {
-        "count": _engine.addedSuites.length
-      });
+      _emit("allSuites", {"count": _engine.addedSuites.length});
     }));
 
-    _emit("start", {
-      "protocolVersion": "0.1.0",
-      "runnerVersion": testVersion
-    });
+    _emit("start", {"protocolVersion": "0.1.0", "runnerVersion": testVersion});
   }
 
   void pause() {
@@ -127,22 +122,26 @@
     var id = _nextID++;
     _liveTestIDs[liveTest] = id;
     _emit("testStart", {
-      "test": _addFrameInfo(suiteConfig, {
-        "id": id,
-        "name": liveTest.test.name, 
-        "suiteID": suiteID,
-        "groupIDs": groupIDs,
-        "metadata": _serializeMetadata(suiteConfig, liveTest.test.metadata)
-      }, liveTest.test, liveTest.suite.platform)
+      "test": _addFrameInfo(
+          suiteConfig,
+          {
+            "id": id,
+            "name": liveTest.test.name,
+            "suiteID": suiteID,
+            "groupIDs": groupIDs,
+            "metadata": _serializeMetadata(suiteConfig, liveTest.test.metadata)
+          },
+          liveTest.test,
+          liveTest.suite.platform)
     });
 
     /// Convert the future to a stream so that the subscription can be paused or
     /// canceled.
-    _subscriptions.add(liveTest.onComplete.asStream().listen((_) =>
-        _onComplete(liveTest)));
+    _subscriptions.add(
+        liveTest.onComplete.asStream().listen((_) => _onComplete(liveTest)));
 
-    _subscriptions.add(liveTest.onError.listen((error) =>
-        _onError(liveTest, error.error, error.stackTrace)));
+    _subscriptions.add(liveTest.onError
+        .listen((error) => _onError(liveTest, error.error, error.stackTrace)));
 
     _subscriptions.add(liveTest.onMessage.listen((message) {
       _emit("print", {
@@ -209,14 +208,18 @@
 
       var suiteConfig = _configFor(suite);
       _emit("group", {
-        "group": _addFrameInfo(suiteConfig, {
-          "id": id,
-          "suiteID": _idForSuite(suite),
-          "parentID": parentID,
-          "name": group.name,
-          "metadata": _serializeMetadata(suiteConfig, group.metadata),
-          "testCount": group.testCount
-        }, group, suite.platform)
+        "group": _addFrameInfo(
+            suiteConfig,
+            {
+              "id": id,
+              "suiteID": _idForSuite(suite),
+              "parentID": parentID,
+              "name": group.name,
+              "metadata": _serializeMetadata(suiteConfig, group.metadata),
+              "testCount": group.testCount
+            },
+            group,
+            suite.platform)
       });
       parentID = id;
       return id;
@@ -249,7 +252,7 @@
       "error": error.toString(),
       "stackTrace":
           terseChain(stackTrace, verbose: liveTest.test.metadata.verboseTrace)
-          .toString(),
+              .toString(),
       "isFailure": error is TestFailure
     });
   }
diff --git a/pub/test/lib/src/runner/runner_suite.dart b/pub/test/lib/src/runner/runner_suite.dart
index 0f5612b..45cb6d9 100644
--- a/pub/test/lib/src/runner/runner_suite.dart
+++ b/pub/test/lib/src/runner/runner_suite.dart
@@ -47,8 +47,11 @@
 
   /// A shortcut constructor for creating a [RunnerSuite] that never goes into
   /// debugging mode.
-  factory RunnerSuite(Environment environment, SuiteConfiguration config,
-      Group group, {String path, TestPlatform platform, OperatingSystem os,
+  factory RunnerSuite(
+      Environment environment, SuiteConfiguration config, Group group,
+      {String path,
+      TestPlatform platform,
+      OperatingSystem os,
       AsyncFunction onClose}) {
     var controller = new RunnerSuiteController(environment, config, group,
         path: path, platform: platform, os: os, onClose: onClose);
@@ -56,7 +59,7 @@
   }
 
   RunnerSuite._(this._controller, Group group, String path,
-          TestPlatform platform, OperatingSystem os)
+      TestPlatform platform, OperatingSystem os)
       : super(group, path: path, platform: platform, os: os);
 
   RunnerSuite filter(bool callback(Test test)) {
@@ -91,8 +94,10 @@
   final _onDebuggingController = new StreamController<bool>.broadcast();
 
   RunnerSuiteController(this._environment, this._config, Group group,
-          {String path, TestPlatform platform,
-          OperatingSystem os, AsyncFunction onClose})
+      {String path,
+      TestPlatform platform,
+      OperatingSystem os,
+      AsyncFunction onClose})
       : _onClose = onClose {
     _suite = new RunnerSuite._(this, group, path, platform, os);
   }
@@ -109,8 +114,8 @@
 
   /// The backing function for [suite.close].
   Future _close() => _closeMemo.runOnce(() async {
-    _onDebuggingController.close();
-    if (_onClose != null) await _onClose();
-  });
+        _onDebuggingController.close();
+        if (_onClose != null) await _onClose();
+      });
   final _closeMemo = new AsyncMemoizer();
 }
diff --git a/pub/test/lib/src/runner/runner_test.dart b/pub/test/lib/src/runner/runner_test.dart
index 3ae83d6..70b8eab 100644
--- a/pub/test/lib/src/runner/runner_test.dart
+++ b/pub/test/lib/src/runner/runner_test.dart
@@ -33,13 +33,13 @@
   /// The function used to reformat errors' stack traces.
   final _MapTrace _mapTrace;
 
-  RunnerTest(this.name, this.metadata, Trace trace, this._channel,
-      _MapTrace mapTrace)
+  RunnerTest(
+      this.name, this.metadata, Trace trace, this._channel, _MapTrace mapTrace)
       : trace = trace == null ? null : new Trace.from(mapTrace(trace)),
         _mapTrace = mapTrace;
 
-  RunnerTest._(this.name, this.metadata, this.trace, this._channel,
-      this._mapTrace);
+  RunnerTest._(
+      this.name, this.metadata, this.trace, this._channel, this._mapTrace);
 
   LiveTest load(Suite suite, {Iterable<Group> groups}) {
     var controller;
@@ -48,10 +48,7 @@
       controller.setState(const State(Status.running, Result.success));
 
       testChannel = _channel.virtualChannel();
-      _channel.sink.add({
-        'command': 'run',
-        'channel': testChannel.id
-      });
+      _channel.sink.add({'command': 'run', 'channel': testChannel.id});
 
       testChannel.stream.listen((message) {
         switch (message['type']) {
@@ -62,10 +59,8 @@
             break;
 
           case 'state-change':
-            controller.setState(
-                new State(
-                    new Status.parse(message['status']),
-                    new Result.parse(message['result'])));
+            controller.setState(new State(new Status.parse(message['status']),
+                new Result.parse(message['result'])));
             break;
 
           case 'message':
@@ -113,11 +108,7 @@
 
   Test forPlatform(TestPlatform platform, {OperatingSystem os}) {
     if (!metadata.testOn.evaluate(platform, os: os)) return null;
-    return new RunnerTest._(
-        name,
-        metadata.forPlatform(platform, os: os),
-        trace,
-        _channel,
-        _mapTrace);
+    return new RunnerTest._(name, metadata.forPlatform(platform, os: os), trace,
+        _channel, _mapTrace);
   }
 }
diff --git a/pub/test/lib/src/runner/spawn_hybrid.dart b/pub/test/lib/src/runner/spawn_hybrid.dart
index 228ff98..84ff560 100644
--- a/pub/test/lib/src/runner/spawn_hybrid.dart
+++ b/pub/test/lib/src/runner/spawn_hybrid.dart
@@ -42,13 +42,13 @@
 
       return new IsolateChannel.connectReceive(port)
           .transform(disconnector)
-          .transformSink(new StreamSinkTransformer.fromHandlers(
-              handleDone: (sink) {
-                // If the user closes the stream channel, kill the isolate.
-                isolate.kill();
-                onExitPort.close();
-                sink.close();
-              }));
+          .transformSink(
+              new StreamSinkTransformer.fromHandlers(handleDone: (sink) {
+        // If the user closes the stream channel, kill the isolate.
+        isolate.kill();
+        onExitPort.close();
+        sink.close();
+      }));
     } catch (error, stackTrace) {
       port.close();
       onExitPort.close();
diff --git a/pub/test/lib/src/runner/version.dart b/pub/test/lib/src/runner/version.dart
index 261764b..363a9a1 100644
--- a/pub/test/lib/src/runner/version.dart
+++ b/pub/test/lib/src/runner/version.dart
@@ -56,6 +56,7 @@
 
       return "$version (from $path)";
 
-    default: return null;
+    default:
+      return null;
   }
 })();
diff --git a/pub/test/lib/src/runner/vm/platform.dart b/pub/test/lib/src/runner/vm/platform.dart
index 27d01c3..22fc2b4 100644
--- a/pub/test/lib/src/runner/vm/platform.dart
+++ b/pub/test/lib/src/runner/vm/platform.dart
@@ -39,11 +39,11 @@
     }());
 
     // Once the connection is closed by either end, kill the isolate.
-    return channel.transformStream(
-        new StreamTransformer.fromHandlers(handleDone: (sink) {
-          if (isolate != null) isolate.kill();
-          sink.close();
-        }));
+    return channel
+        .transformStream(new StreamTransformer.fromHandlers(handleDone: (sink) {
+      if (isolate != null) isolate.kill();
+      sink.close();
+    }));
   }
 
   /// Spawns an isolate and passes it [message].
@@ -52,7 +52,8 @@
   /// serialized tests over that channel.
   Future<Isolate> _spawnIsolate(String path, SendPort message) async {
     if (_config.pubServeUrl == null) {
-      return await dart.runInIsolate('''
+      return await dart.runInIsolate(
+          '''
         import "dart:isolate";
 
         import "package:stream_channel/stream_channel.dart";
@@ -69,22 +70,26 @@
           });
           new IsolateChannel.connectSend(message).pipe(channel);
         }
-      ''', message, checked: true);
+      ''',
+          message,
+          checked: true);
     }
 
-    var url = _config.pubServeUrl.resolveUri(
-        p.toUri(p.relative(path, from: 'test') + '.vm_test.dart'));
+    var url = _config.pubServeUrl
+        .resolveUri(p.toUri(p.relative(path, from: 'test') + '.vm_test.dart'));
 
     try {
       return await Isolate.spawnUri(url, [], message, checked: true);
     } on IsolateSpawnException catch (error) {
       if (error.message.contains("OS Error: Connection refused") ||
           error.message.contains("The remote computer refused")) {
-        throw new LoadException(path,
+        throw new LoadException(
+            path,
             "Error getting $url: Connection refused\n"
             'Make sure "pub serve" is running.');
       } else if (error.message.contains("404 Not Found")) {
-        throw new LoadException(path,
+        throw new LoadException(
+            path,
             "Error getting $url: 404 Not Found\n"
             'Make sure "pub serve" is serving the test/ directory.');
       }
diff --git a/pub/test/lib/src/util/dart.dart b/pub/test/lib/src/util/dart.dart
index c8cac8c..7d690ee 100644
--- a/pub/test/lib/src/util/dart.dart
+++ b/pub/test/lib/src/util/dart.dart
@@ -21,8 +21,8 @@
 ///
 /// If [resolver] is passed, its package resolution strategy is used to resolve
 /// code in the spawned isolate. It defaults to [PackageResolver.current].
-Future<Isolate> runInIsolate(String code, message, {PackageResolver resolver,
-    bool checked, SendPort onExit}) async {
+Future<Isolate> runInIsolate(String code, message,
+    {PackageResolver resolver, bool checked, SendPort onExit}) async {
   resolver ??= PackageResolver.current;
   return await Isolate.spawnUri(
       new Uri.dataFromString(code,
@@ -62,8 +62,8 @@
 ///
 /// This will return `null` if [context] contains an invalid string or does not
 /// contain [span].
-SourceSpan contextualizeSpan(SourceSpan span, StringLiteral context,
-    SourceFile file) {
+SourceSpan contextualizeSpan(
+    SourceSpan span, StringLiteral context, SourceFile file) {
   var contextRunes = new StringLiteralIterator(context)..moveNext();
 
   for (var i = 0; i < span.start.offset; i++) {
diff --git a/pub/test/lib/src/util/forkable_stream.dart b/pub/test/lib/src/util/forkable_stream.dart
index 6a8694d..22b81f1 100644
--- a/pub/test/lib/src/util/forkable_stream.dart
+++ b/pub/test/lib/src/util/forkable_stream.dart
@@ -125,8 +125,8 @@
   void _onPause(StreamController<T> controller) {
     if (controller.isClosed) return;
     if (_subscription.isPaused) return;
-    if (_controllers.any((controller) =>
-        controller.hasListener && !controller.isPaused)) {
+    if (_controllers
+        .any((controller) => controller.hasListener && !controller.isPaused)) {
       return;
     }
 
@@ -163,4 +163,3 @@
     _controllers.clear();
   }
 }
-
diff --git a/pub/test/lib/src/util/io.dart b/pub/test/lib/src/util/io.dart
index 8d4987b..3f94b80 100644
--- a/pub/test/lib/src/util/io.dart
+++ b/pub/test/lib/src/util/io.dart
@@ -24,8 +24,7 @@
 
 /// The version of the Dart SDK currently in use.
 final Version _sdkVersion = new Version.parse(
-    new File(p.join(sdkDir, 'version'))
-        .readAsStringSync().trim());
+    new File(p.join(sdkDir, 'version')).readAsStringSync().trim());
 
 /// Returns the current operating system.
 final OperatingSystem currentOS = (() {
@@ -62,7 +61,8 @@
 
 /// Creates a temporary directory and returns its path.
 String createTempDir() => new Directory(_tempDir)
-    .createTempSync('dart_test_').resolveSymbolicLinksSync();
+    .createTempSync('dart_test_')
+    .resolveSymbolicLinksSync();
 
 /// Creates a temporary directory and passes its path to [fn].
 ///
@@ -95,12 +95,16 @@
 
   return input.map((list) {
     var previous;
-    return list.reversed.where((byte) {
-      if (byte == 0) return false;
-      if (byte == _carriageReturn && previous == _newline) return false;
-      previous = byte;
-      return true;
-    }).toList().reversed.toList();
+    return list.reversed
+        .where((byte) {
+          if (byte == 0) return false;
+          if (byte == _carriageReturn && previous == _newline) return false;
+          previous = byte;
+          return true;
+        })
+        .toList()
+        .reversed
+        .toList();
   });
 }
 
@@ -111,9 +115,7 @@
 /// [canUseSpecialChars].
 void warn(String message, {bool color}) {
   if (color == null) color = canUseSpecialChars;
-  var header = color
-      ? "\u001b[33mWarning:\u001b[0m"
-      : "Warning:";
+  var header = color ? "\u001b[33mWarning:\u001b[0m" : "Warning:";
   stderr.writeln(wordWrap("$header $message\n"));
 }
 
diff --git a/pub/test/lib/src/util/path_handler.dart b/pub/test/lib/src/util/path_handler.dart
index 5659713..1dbe8a9 100644
--- a/pub/test/lib/src/util/path_handler.dart
+++ b/pub/test/lib/src/util/path_handler.dart
@@ -39,7 +39,7 @@
     var handlerIndex;
     var node = _paths;
     var components = p.url.split(request.url.path);
-    for (var i = 0; i < components.length; i++ ) {
+    for (var i = 0; i < components.length; i++) {
       node = node.children[components[i]];
       if (node == null) break;
       if (node.handler == null) continue;
@@ -49,8 +49,8 @@
 
     if (handler == null) return new shelf.Response.notFound("Not found.");
 
-    return handler(request.change(
-        path: p.url.joinAll(components.take(handlerIndex + 1))));
+    return handler(
+        request.change(path: p.url.joinAll(components.take(handlerIndex + 1))));
   }
 }
 
diff --git a/pub/test/lib/src/util/remote_exception.dart b/pub/test/lib/src/util/remote_exception.dart
index e43cd75..f68ff21 100644
--- a/pub/test/lib/src/util/remote_exception.dart
+++ b/pub/test/lib/src/util/remote_exception.dart
@@ -66,8 +66,7 @@
   /// The returned [AsyncError] is guaranteed to have a [RemoteException] as its
   /// error and a [Chain] as its stack trace.
   static AsyncError deserialize(serialized) {
-    return new AsyncError(
-        _deserializeException(serialized),
+    return new AsyncError(_deserializeException(serialized),
         new Chain.parse(serialized['stackChain']));
   }
 
diff --git a/pub/test/lib/src/util/stream_queue.dart b/pub/test/lib/src/util/stream_queue.dart
index 1c2e3b2..ba8df3f 100644
--- a/pub/test/lib/src/util/stream_queue.dart
+++ b/pub/test/lib/src/util/stream_queue.dart
@@ -104,9 +104,8 @@
 
   /// Create a `StreamQueue` of the events of [source].
   StreamQueue(Stream<T> source)
-      : _sourceStream = source is ForkableStream
-          ? source
-          : new ForkableStream(source);
+      : _sourceStream =
+            source is ForkableStream ? source : new ForkableStream(source);
 
   /// Asks if the stream has any more events.
   ///
@@ -440,7 +439,7 @@
 
   void close(Queue<Result> events) {
     var errorFuture =
-        new Future.sync(() => throw new StateError("No elements"));
+        new Future<T>.sync(() => throw new StateError("No elements"));
     _completer.complete(errorFuture);
   }
 }
@@ -488,7 +487,7 @@
   final _completer = new Completer<List<T>>();
 
   /// List collecting events until enough have been seen.
-  final List _list = <T>[];
+  final _list = <T>[];
 
   /// Number of events to capture.
   ///
@@ -602,8 +601,9 @@
       for (var event in events) {
         event.addTo(controller);
       }
-      controller.addStream(_getRestStream(), cancelOnError: false)
-                .whenComplete(controller.close);
+      controller
+          .addStream(_getRestStream(), cancelOnError: false)
+          .whenComplete(controller.close);
       _completer.setSourceStream(controller.stream);
     }
   }
@@ -689,7 +689,8 @@
       }
 
       var fork = _streamQueue._sourceStream.fork();
-      controller.addStream(fork, cancelOnError: false)
+      controller
+          .addStream(fork, cancelOnError: false)
           .whenComplete(controller.close);
       _completer.setSourceStream(controller.stream);
     }
diff --git a/pub/test/lib/src/util/string_literal_iterator.dart b/pub/test/lib/src/util/string_literal_iterator.dart
index 59f0372..665f989 100644
--- a/pub/test/lib/src/util/string_literal_iterator.dart
+++ b/pub/test/lib/src/util/string_literal_iterator.dart
@@ -117,7 +117,8 @@
       var start = string.contentsOffset - string.offset;
 
       // Compensate for the opening and closing quotes.
-      var end = start + string.literal.lexeme.length -
+      var end = start +
+          string.literal.lexeme.length -
           2 * (string.isMultiline ? 3 : 1) -
           (string.isRaw ? 1 : 0);
       var text = string.literal.lexeme.substring(start, end);
diff --git a/pub/test/lib/src/utils.dart b/pub/test/lib/src/utils.dart
index 5a0f4ff..17330a4 100644
--- a/pub/test/lib/src/utils.dart
+++ b/pub/test/lib/src/utils.dart
@@ -45,13 +45,8 @@
 /// Directories that are specific to OS X.
 ///
 /// This is used to try to distinguish OS X and Linux in [currentOSGuess].
-final _macOSDirectories = new Set<String>.from([
-  "/Applications",
-  "/Library",
-  "/Network",
-  "/System",
-  "/Users"
-]);
+final _macOSDirectories = new Set<String>.from(
+    ["/Applications", "/Library", "/Network", "/System", "/Users"]);
 
 /// Returns the best guess for the current operating system without using
 /// `dart:io`.
@@ -86,7 +81,7 @@
 
   String toString() => '($first, $last)';
 
-  bool operator==(other) {
+  bool operator ==(other) {
     if (other is! Pair) return false;
     return other.first == first && other.last == last;
   }
@@ -99,7 +94,7 @@
 /// Many exceptions include the exception class name at the beginning of their
 /// [toString], so we remove that if it exists.
 String getErrorMessage(error) =>
-  error.toString().replaceFirst(_exceptionPrefix, '');
+    error.toString().replaceFirst(_exceptionPrefix, '');
 
 /// Indent each line in [string] by [size] spaces.
 ///
@@ -180,8 +175,8 @@
 /// If [verbose] is `true`, returns the chain for [stackTrace] unmodified.
 Chain terseChain(StackTrace stackTrace, {bool verbose: false}) {
   if (verbose) return new Chain.forTrace(stackTrace);
-  return new Chain.forTrace(stackTrace).foldFrames((frame) =>
-      frame.package == 'test' || frame.package == 'stream_channel',
+  return new Chain.forTrace(stackTrace).foldFrames(
+      (frame) => frame.package == 'test' || frame.package == 'stream_channel',
       terse: true);
 }
 
@@ -205,14 +200,15 @@
       }
     }
   }
+
   helper(nested);
   return result;
 }
 
 /// Like [runZoned], but [zoneValues] are set for the callbacks in
 /// [zoneSpecification] and [onError].
-runZonedWithValues(body(), {Map zoneValues,
-    ZoneSpecification zoneSpecification, Function onError}) {
+runZonedWithValues(body(),
+    {Map zoneValues, ZoneSpecification zoneSpecification, Function onError}) {
   return runZoned(() {
     return runZoned(body,
         zoneSpecification: zoneSpecification, onError: onError);
@@ -242,7 +238,7 @@
       var buffer = new StringBuffer();
       buffer.write(words.first);
       buffer.write(' ...');
-      for ( ; i < words.length; i++) {
+      for (; i < words.length; i++) {
         buffer.write(' ');
         buffer.write(words[i]);
       }
@@ -326,14 +322,17 @@
 /// If the subscription is canceled, any pending operations are canceled as
 /// well.
 Stream/*<T>*/ inCompletionOrder/*<T>*/(
-    Iterable<CancelableOperation/*<T>*/> operations) {
+    Iterable<CancelableOperation/*<T>*/ > operations) {
   var operationSet = operations.toSet();
-  var controller = new StreamController/*<T>*/(sync: true, onCancel: () {
-    return Future.wait(operationSet.map((operation) => operation.cancel()));
-  });
+  var controller = new StreamController/*<T>*/(
+      sync: true,
+      onCancel: () {
+        return Future.wait(operationSet.map((operation) => operation.cancel()));
+      });
 
   for (var operation in operationSet) {
-    operation.value.then((value) => controller.add(value))
+    operation.value
+        .then((value) => controller.add(value))
         .catchError(controller.addError)
         .whenComplete(() {
       operationSet.remove(operation);
@@ -394,7 +393,9 @@
 
 /// Throws an [ArgumentError] if [message] isn't recursively JSON-safe.
 void ensureJsonEncodable(Object message) {
-  if (message == null || message is String || message is num ||
+  if (message == null ||
+      message is String ||
+      message is num ||
       message is bool) {
     // JSON-encodable, hooray!
   } else if (message is List) {
@@ -416,9 +417,7 @@
 
 /// Prepends a vertical bar to [text].
 String addBar(String text) => prefixLines(text, "${glyph.verticalLine} ",
-    first: "${glyph.downEnd} ",
-    last: "${glyph.upEnd} ",
-    single: "| ");
+    first: "${glyph.downEnd} ", last: "${glyph.upEnd} ", single: "| ");
 
 /// Indents [text], and adds a bullet at the beginning.
 String addBullet(String text) =>
@@ -433,8 +432,8 @@
 /// prefixed with those instead. If [single] is passed, it's used if there's
 /// only a single line; otherwise, [first], [last], or [prefix] is used, in that
 /// order of precedence.
-String prefixLines(String text, String prefix, {String first, String last,
-    String single}) {
+String prefixLines(String text, String prefix,
+    {String first, String last, String single}) {
   first ??= prefix;
   last ??= prefix;
   single ??= first ?? last ?? prefix;
diff --git a/pub/test/lib/test.dart b/pub/test/lib/test.dart
index e6e81ff..13d182f 100644
--- a/pub/test/lib/test.dart
+++ b/pub/test/lib/test.dart
@@ -55,10 +55,8 @@
   // finished being defined.
   _globalDeclarer = new Declarer();
   scheduleMicrotask(() async {
-    var suite = new RunnerSuite(
-        const PluginEnvironment(),
-        SuiteConfiguration.empty,
-        _globalDeclarer.build(),
+    var suite = new RunnerSuite(const PluginEnvironment(),
+        SuiteConfiguration.empty, _globalDeclarer.build(),
         path: p.prettyUri(Uri.base),
         platform: TestPlatform.vm,
         os: currentOSGuess);
@@ -125,11 +123,11 @@
 /// If multiple platforms match, the annotations apply in order as through
 /// they were in nested groups.
 void test(description, body(),
-        {String testOn,
-        Timeout timeout,
-        skip,
-        tags,
-        Map<String, dynamic> onPlatform}) {
+    {String testOn,
+    Timeout timeout,
+    skip,
+    tags,
+    Map<String, dynamic> onPlatform}) {
   _declarer.test(description.toString(), body,
       testOn: testOn,
       timeout: timeout,
@@ -141,7 +139,7 @@
   // `main()` in JS stack traces in order to properly determine the line and
   // column where the test was defined. See sdk#26705.
   return;
-  return;
+  return; // ignore: dead_code
 }
 
 /// Creates a group of tests.
@@ -192,19 +190,23 @@
 /// If multiple platforms match, the annotations apply in order as through
 /// they were in nested groups.
 void group(description, body(),
-        {String testOn,
-        Timeout timeout,
-        skip,
-        tags,
-        Map<String, dynamic> onPlatform}) {
+    {String testOn,
+    Timeout timeout,
+    skip,
+    tags,
+    Map<String, dynamic> onPlatform}) {
   _declarer.group(description.toString(), body,
-      testOn: testOn, timeout: timeout, skip: skip, tags: tags);
+      testOn: testOn,
+      timeout: timeout,
+      skip: skip,
+      tags: tags,
+      onPlatform: onPlatform);
 
   // Force dart2js not to inline this function. We need it to be separate from
   // `main()` in JS stack traces in order to properly determine the line and
   // column where the test was defined. See sdk#26705.
   return;
-  return;
+  return; // ignore: dead_code
 }
 
 /// Registers a function to be run before tests.
diff --git a/pub/test/pubspec.yaml b/pub/test/pubspec.yaml
index ae3f56e..944856f 100644
--- a/pub/test/pubspec.yaml
+++ b/pub/test/pubspec.yaml
@@ -1,12 +1,12 @@
 name: test
-version: 0.12.20
+version: 0.12.21
 author: Dart Team <misc@dartlang.org>
 description: A library for writing dart unit tests.
 homepage: https://github.com/dart-lang/test
 environment:
   sdk: '>=1.14.0 <2.0.0'
 dependencies:
-  analyzer: '>=0.23.0 <0.30.0'
+  analyzer: '>=0.23.0 <0.31.0'
   args: '^0.13.1'
   async: '^1.13.0'
   barback: '>=0.14.0 <0.16.0'
@@ -27,7 +27,7 @@
   source_maps: '^0.10.2'
   source_span: '^1.0.0'
   stack_trace: '^1.2.1'
-  stream_channel: '^1.3.1'
+  stream_channel: '^1.6.0'
   string_scanner: '>=0.1.1 <2.0.0'
   term_glyph: '^1.0.0'
   web_socket_channel: '^1.0.0'
@@ -35,7 +35,7 @@
 
   # Use a tight version constraint to ensure that a constraint on matcher
   # properly constrains all features it provides.
-  matcher: '>=0.12.0 <0.12.1'
+  matcher: '>=0.12.1 <0.12.2'
 dev_dependencies:
   fake_async: '^0.1.2'
   http: '^0.11.0'
diff --git a/pub/test/tool/README.md b/pub/test/tool/README.md
new file mode 100644
index 0000000..42f2fb9
--- /dev/null
+++ b/pub/test/tool/README.md
@@ -0,0 +1,7 @@
+`host.dart` is the source for `lib/src/runner/browser/static/host.dart.js`.
+
+To updated it, run:
+
+```console
+dart2js tool/host.dart -o lib/src/runner/browser/static/host.dart.js
+```
diff --git a/pub/test/lib/src/runner/browser/static/host.dart b/pub/test/tool/host.dart
similarity index 98%
rename from pub/test/lib/src/runner/browser/static/host.dart
rename to pub/test/tool/host.dart
index 675c70d..5234147 100644
--- a/pub/test/lib/src/runner/browser/static/host.dart
+++ b/pub/test/tool/host.dart
@@ -2,6 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+@JS()
+library test.host;
+
 import 'dart:async';
 import 'dart:convert';
 import 'dart:html';
@@ -159,8 +162,8 @@
     controller.local.sink.add(JSON.decode(message.data));
   });
 
-  controller.local.stream.listen(
-      (message) => webSocket.send(JSON.encode(message)));
+  controller.local.stream
+      .listen((message) => webSocket.send(JSON.encode(message)));
 
   return new MultiChannel(controller.foreign);
 }
diff --git a/pub/usage/.analysis_options b/pub/usage/.analysis_options
deleted file mode 100644
index a10d4c5..0000000
--- a/pub/usage/.analysis_options
+++ /dev/null
@@ -1,2 +0,0 @@
-analyzer:
-  strong-mode: true
diff --git a/pub/usage/.gitignore b/pub/usage/.gitignore
index e3225ef..a9df6e6 100644
--- a/pub/usage/.gitignore
+++ b/pub/usage/.gitignore
@@ -2,4 +2,5 @@
 .idea/
 .pub/
 build/
+doc/api/
 pubspec.lock
diff --git a/pub/usage/.travis.yml b/pub/usage/.travis.yml
index 9e27d1f..96ba4fc 100644
--- a/pub/usage/.travis.yml
+++ b/pub/usage/.travis.yml
@@ -1,3 +1,4 @@
 language: dart
+dart: dev
 sudo: false
 script: ./tool/travis.sh
diff --git a/pub/usage/BUILD.gn b/pub/usage/BUILD.gn
index 67f88f7..221ce8b 100644
--- a/pub/usage/BUILD.gn
+++ b/pub/usage/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for usage-3.0.1
+# This file is generated by importer.py for usage-3.3.0
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/usage/analysis_options.yaml b/pub/usage/analysis_options.yaml
new file mode 100644
index 0000000..2ef22c9
--- /dev/null
+++ b/pub/usage/analysis_options.yaml
@@ -0,0 +1,8 @@
+analyzer:
+  strong-mode: true
+linter:
+  rules:
+    - annotate_overrides
+    - directives_ordering
+    - empty_constructor_bodies
+    - empty_statements
diff --git a/pub/usage/changelog.md b/pub/usage/changelog.md
index 7558a01..351cb38 100644
--- a/pub/usage/changelog.md
+++ b/pub/usage/changelog.md
@@ -1,5 +1,23 @@
 # Changelog
 
+## 3.3.0
+- added a `close()` method to the `Analytics` class
+- change our minimum SDK from `1.24.0-dev` to `1.24.0` stable
+
+## 3.2.0
+- expose the `Analytics.applicationName` and `Analytics.applicationVersion`
+  properties
+- make it easier for clients to extend the `AnalyticsIO` class
+- allow for custom parameters when sending a screenView
+
+## 3.1.1
+- make Analytics.clientId available immediately
+
+## 3.1.0
+- switch the technique we use to determine the locale to the new dart:io
+  `Platform.localeName` field
+- change our minimum SDK version to `1.24.0`
+
 ## 3.0.1
 - expose the `Analytics.clientId` field
 
diff --git a/pub/usage/example/ga.dart b/pub/usage/example/ga.dart
index bf0807e..ad64249 100644
--- a/pub/usage/example/ga.dart
+++ b/pub/usage/example/ga.dart
@@ -28,4 +28,8 @@
   await ga.sendTiming('writeDuration', 123);
   await ga.sendEvent('create', 'consoleapp', label: 'Console App');
   print('pinged ${ua}');
+
+  await ga.waitForLastPing();
+
+  ga.close();
 }
diff --git a/pub/usage/lib/src/usage_impl.dart b/pub/usage/lib/src/usage_impl.dart
index 3f5eee4..df529e3 100644
--- a/pub/usage/lib/src/usage_impl.dart
+++ b/pub/usage/lib/src/usage_impl.dart
@@ -60,10 +60,12 @@
   static const String _defaultAnalyticsUrl =
       'https://www.google-analytics.com/collect';
 
-  /**
-   * Tracking ID / Property ID.
-   */
+  @override
   final String trackingId;
+  @override
+  final String applicationName;
+  @override
+  final String applicationVersion;
 
   final PersistentProperties properties;
   final PostHandler postHandler;
@@ -73,6 +75,7 @@
 
   final List<Future> _futures = [];
 
+  @override
   AnalyticsOpt analyticsOpt = AnalyticsOpt.optOut;
 
   String _url;
@@ -81,9 +84,7 @@
       new StreamController.broadcast(sync: true);
 
   AnalyticsImpl(this.trackingId, this.properties, this.postHandler,
-      {String applicationName,
-      String applicationVersion,
-      String analyticsUrl}) {
+      {this.applicationName, this.applicationVersion, String analyticsUrl}) {
     assert(trackingId != null);
 
     if (applicationName != null) setSessionValue('an', applicationName);
@@ -94,6 +95,7 @@
 
   bool _firstRun;
 
+  @override
   bool get firstRun {
     if (_firstRun == null) {
       _firstRun = properties['firstRun'] == null;
@@ -106,9 +108,7 @@
     return _firstRun;
   }
 
-  /**
-   * Will analytics data be sent?
-   */
+  @override
   bool get enabled {
     bool optIn = analyticsOpt == AnalyticsOpt.optIn;
     return optIn
@@ -116,30 +116,39 @@
         : properties['enabled'] != false;
   }
 
-  /**
-   * Enable or disable sending of analytics data.
-   */
+  @override
   set enabled(bool value) {
     properties['enabled'] = value;
   }
 
-  Future sendScreenView(String viewName) {
+  @override
+  Future sendScreenView(String viewName, {Map<String, String> parameters}) {
     Map<String, dynamic> args = {'cd': viewName};
+    if (parameters != null) {
+      args.addAll(parameters);
+    }
     return _sendPayload('screenview', args);
   }
 
-  Future sendEvent(String category, String action, {String label, int value}) {
+  @override
+  Future sendEvent(String category, String action,
+      {String label, int value, Map<String, String> parameters}) {
     Map<String, dynamic> args = {'ec': category, 'ea': action};
     if (label != null) args['el'] = label;
     if (value != null) args['ev'] = value;
+    if (parameters != null) {
+      args.addAll(parameters);
+    }
     return _sendPayload('event', args);
   }
 
+  @override
   Future sendSocial(String network, String action, String target) {
     Map<String, dynamic> args = {'sn': network, 'sa': action, 'st': target};
     return _sendPayload('social', args);
   }
 
+  @override
   Future sendTiming(String variableName, int time,
       {String category, String label}) {
     Map<String, dynamic> args = {'utv': variableName, 'utt': time};
@@ -148,12 +157,14 @@
     return _sendPayload('timing', args);
   }
 
+  @override
   AnalyticsTimer startTimer(String variableName,
       {String category, String label}) {
     return new AnalyticsTimer(this, variableName,
         category: category, label: label);
   }
 
+  @override
   Future sendException(String description, {bool fatal}) {
     // We trim exceptions to a max length; google analytics will apply it's own
     // truncation, likely around 150 chars or so.
@@ -177,8 +188,10 @@
     return _sendPayload('exception', args);
   }
 
+  @override
   dynamic getSessionValue(String param) => _variableMap[param];
 
+  @override
   void setSessionValue(String param, dynamic value) {
     if (value == null) {
       _variableMap.remove(param);
@@ -187,8 +200,10 @@
     }
   }
 
+  @override
   Stream<Map<String, dynamic>> get onSend => _sendController.stream;
 
+  @override
   Future waitForLastPing({Duration timeout}) {
     Future f = Future.wait(_futures).catchError((e) => null);
 
@@ -200,13 +215,10 @@
   }
 
   @override
-  String get clientId => properties['clientId'];
+  void close() => postHandler.close();
 
-  void _initClientId() {
-    if (clientId == null) {
-      properties['clientId'] = new Uuid().generateV4();
-    }
-  }
+  @override
+  String get clientId => properties['clientId'] ??= new Uuid().generateV4();
 
   /**
    * Send raw data to analytics. Callers should generally use one of the typed
@@ -227,8 +239,6 @@
     if (!enabled) return new Future.value();
 
     if (_bucket.removeDrop()) {
-      _initClientId();
-
       _variableMap.forEach((key, value) {
         args[key] = value;
       });
@@ -267,6 +277,10 @@
 
   dynamic operator [](String key);
   void operator []=(String key, dynamic value);
+
+  /// Re-read settings from the backing store. This may be a no-op on some
+  /// platforms.
+  void syncSettings();
 }
 
 /**
@@ -280,4 +294,7 @@
  */
 abstract class PostHandler {
   Future sendPost(String url, Map<String, dynamic> parameters);
+
+  /// Free any used resources.
+  void close();
 }
diff --git a/pub/usage/lib/src/usage_impl_html.dart b/pub/usage/lib/src/usage_impl_html.dart
index 7752fe5..c15cde6 100644
--- a/pub/usage/lib/src/usage_impl_html.dart
+++ b/pub/usage/lib/src/usage_impl_html.dart
@@ -30,11 +30,15 @@
   }
 }
 
+typedef Future<HttpRequest> HttpRequestor(String url,
+    {String method, sendData});
+
 class HtmlPostHandler extends PostHandler {
-  final Function mockRequestor;
+  final HttpRequestor mockRequestor;
 
-  HtmlPostHandler({Function this.mockRequestor});
+  HtmlPostHandler({this.mockRequestor});
 
+  @override
   Future sendPost(String url, Map<String, dynamic> parameters) {
     int viewportWidth = document.documentElement.clientWidth;
     int viewportHeight = document.documentElement.clientHeight;
@@ -42,12 +46,16 @@
     parameters['vp'] = '${viewportWidth}x$viewportHeight';
 
     String data = postEncode(parameters);
-    var request = mockRequestor == null ? HttpRequest.request : mockRequestor;
-    return request(url, method: 'POST', sendData: data).catchError((e) {
+    HttpRequestor requestor =
+        mockRequestor == null ? HttpRequest.request : mockRequestor;
+    return requestor(url, method: 'POST', sendData: data).catchError((e) {
       // Catch errors that can happen during a request, but that we can't do
       // anything about, e.g. a missing internet connection.
     });
   }
+
+  @override
+  void close() {}
 }
 
 class HtmlPersistentProperties extends PersistentProperties {
@@ -59,8 +67,10 @@
     _map = JSON.decode(str);
   }
 
+  @override
   dynamic operator [](String key) => _map[key];
 
+  @override
   void operator []=(String key, dynamic value) {
     if (value == null) {
       _map.remove(key);
@@ -70,4 +80,7 @@
 
     window.localStorage[name] = JSON.encode(_map);
   }
+
+  @override
+  void syncSettings() {}
 }
diff --git a/pub/usage/lib/src/usage_impl_io.dart b/pub/usage/lib/src/usage_impl_io.dart
index ff1b153..6e82d41 100644
--- a/pub/usage/lib/src/usage_impl_io.dart
+++ b/pub/usage/lib/src/usage_impl_io.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:convert' show JSON;
+import 'dart:convert' show JSON, JsonEncoder;
 import 'dart:io';
 
 import 'package:path/path.dart' as path;
@@ -60,7 +60,7 @@
   }
 }
 
-String _userHomeDir() {
+String userHomeDir() {
   String envKey = Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
   String value = Platform.environment[envKey];
   return value == null ? '.' : value;
@@ -77,15 +77,21 @@
   final String _userAgent;
   final HttpClient mockClient;
 
-  IOPostHandler({HttpClient this.mockClient}) : _userAgent = _createUserAgent();
+  HttpClient _client;
 
+  IOPostHandler({this.mockClient}) : _userAgent = _createUserAgent();
+
+  @override
   Future sendPost(String url, Map<String, dynamic> parameters) async {
     String data = postEncode(parameters);
 
-    HttpClient client = mockClient != null ? mockClient : new HttpClient();
-    client.userAgent = _userAgent;
+    if (_client == null) {
+      _client = mockClient != null ? mockClient : new HttpClient();
+      _client.userAgent = _userAgent;
+    }
+
     try {
-      HttpClientRequest req = await client.postUrl(Uri.parse(url));
+      HttpClientRequest req = await _client.postUrl(Uri.parse(url));
       req.write(data);
       HttpClientResponse response = await req.close();
       response.drain();
@@ -94,29 +100,39 @@
       // anything about, e.g. a missing internet connection.
     }
   }
+
+  @override
+  void close() => _client?.close();
 }
 
+JsonEncoder _jsonEncoder = new JsonEncoder.withIndent('  ');
+
 class IOPersistentProperties extends PersistentProperties {
   File _file;
   Map _map;
 
   IOPersistentProperties(String name, {String documentDirPath}) : super(name) {
     String fileName = '.${name.replaceAll(' ', '_')}';
-    documentDirPath ??= _userHomeDir();
+    documentDirPath ??= userHomeDir();
     _file = new File(path.join(documentDirPath, fileName));
-
-    try {
-      if (!_file.existsSync()) _file.createSync();
-      String contents = _file.readAsStringSync();
-      if (contents.isEmpty) contents = '{}';
-      _map = JSON.decode(contents);
-    } catch (_) {
-      _map = {};
+    if (!_file.existsSync()) {
+      _file.createSync();
     }
+    syncSettings();
   }
 
+  IOPersistentProperties.fromFile(File file) : super(path.basename(file.path)) {
+    _file = file;
+    if (!_file.existsSync()) {
+      _file.createSync();
+    }
+    syncSettings();
+  }
+
+  @override
   dynamic operator [](String key) => _map[key];
 
+  @override
   void operator []=(String key, dynamic value) {
     if (value == null && !_map.containsKey(key)) return;
     if (_map[key] == value) return;
@@ -128,15 +144,26 @@
     }
 
     try {
-      _file.writeAsStringSync(JSON.encode(_map) + '\n');
+      _file.writeAsStringSync(_jsonEncoder.convert(_map) + '\n');
     } catch (_) {}
   }
+
+  @override
+  void syncSettings() {
+    try {
+      String contents = _file.readAsStringSync();
+      if (contents.isEmpty) contents = '{}';
+      _map = JSON.decode(contents);
+    } catch (_) {
+      _map = {};
+    }
+  }
 }
 
 /// Return the string for the platform's locale; return's `null` if the locale
 /// can't be determined.
 String getPlatformLocale() {
-  String locale = Platform.environment['LANG'];
+  String locale = Platform.localeName;
   if (locale == null) return null;
 
   if (locale != null) {
diff --git a/pub/usage/lib/usage.dart b/pub/usage/lib/usage.dart
index dfdc54b..e79701c 100644
--- a/pub/usage/lib/usage.dart
+++ b/pub/usage/lib/usage.dart
@@ -47,6 +47,12 @@
    */
   String get trackingId;
 
+  /// The application name.
+  String get applicationName;
+
+  /// The application version.
+  String get applicationVersion;
+
   /**
    * Is this the first time the tool has run?
    */
@@ -77,14 +83,21 @@
 
   /**
    * Sends a screen view hit to Google Analytics.
+   *
+   * [parameters] can be any analytics key/value pair. Useful
+   * for custom dimensions, etc.
    */
-  Future sendScreenView(String viewName);
+  Future sendScreenView(String viewName, {Map<String, String> parameters});
 
   /**
    * Sends an Event hit to Google Analytics. [label] specifies the event label.
    * [value] specifies the event value. Values must be non-negative.
+   *
+   * [parameters] can be any analytics key/value pair. Useful
+   * for custom dimensions, etc.
    */
-  Future sendEvent(String category, String action, {String label, int value});
+  Future sendEvent(String category, String action,
+      {String label, int value, Map<String, String> parameters});
 
   /**
    * Sends a Social hit to Google Analytics. [network] specifies the social
@@ -151,9 +164,15 @@
    * users won't want their CLI app to pause at the end of the process waiting
    * for Google analytics requests to complete. This method allows CLI apps to
    * delay for a short time waiting for GA requests to complete, and then do
-   * something like call `exit()` explicitly themselves.
+   * something like call `dart:io`'s `exit()` explicitly themselves (or the
+   * [close] method below).
    */
   Future waitForLastPing({Duration timeout});
+
+  /// Free any used resources.
+  ///
+  /// The [Analytics] instance should not be used after this call.
+  void close();
 }
 
 enum AnalyticsOpt {
@@ -212,7 +231,13 @@
  * stand-in for that will never ping the GA server, or as a mock in test code.
  */
 class AnalyticsMock implements Analytics {
+  @override
   String get trackingId => 'UA-0';
+  @override
+  String get applicationName => 'mock-app';
+  @override
+  String get applicationVersion => '1.0.0';
+
   final bool logCalls;
 
   /**
@@ -227,30 +252,40 @@
    */
   AnalyticsMock([this.logCalls = false]);
 
+  @override
   bool get firstRun => false;
 
+  @override
   AnalyticsOpt analyticsOpt = AnalyticsOpt.optOut;
 
+  @override
   bool enabled = true;
 
   @override
   String get clientId => '00000000-0000-4000-0000-000000000000';
 
-  Future sendScreenView(String viewName) =>
-      _log('screenView', {'viewName': viewName});
-
-  Future sendEvent(String category, String action, {String label, int value}) {
-    return _log('event', {
-      'category': category,
-      'action': action,
-      'label': label,
-      'value': value
-    });
+  @override
+  Future sendScreenView(String viewName, {Map<String, String> parameters}) {
+    parameters ??= <String, String>{};
+    parameters['viewName'] = viewName;
+    return _log('screenView', parameters);
   }
 
+  @override
+  Future sendEvent(String category, String action,
+      {String label, int value, Map<String, String> parameters}) {
+    parameters ??= <String, String>{};
+    return _log(
+        'event',
+        {'category': category, 'action': action, 'label': label, 'value': value}
+          ..addAll(parameters));
+  }
+
+  @override
   Future sendSocial(String network, String action, String target) =>
       _log('social', {'network': network, 'action': action, 'target': target});
 
+  @override
   Future sendTiming(String variableName, int time,
       {String category, String label}) {
     return _log('timing', {
@@ -261,23 +296,32 @@
     });
   }
 
+  @override
   AnalyticsTimer startTimer(String variableName,
       {String category, String label}) {
     return new AnalyticsTimer(this, variableName,
         category: category, label: label);
   }
 
+  @override
   Future sendException(String description, {bool fatal}) =>
       _log('exception', {'description': description, 'fatal': fatal});
 
+  @override
   dynamic getSessionValue(String param) => null;
 
+  @override
   void setSessionValue(String param, dynamic value) {}
 
+  @override
   Stream<Map<String, dynamic>> get onSend => _sendController.stream;
 
+  @override
   Future waitForLastPing({Duration timeout}) => new Future.value();
 
+  @override
+  void close() {}
+
   Future _log(String hitType, Map m) {
     if (logCalls) {
       print('analytics: ${hitType} ${m}');
diff --git a/pub/usage/pubspec.yaml b/pub/usage/pubspec.yaml
index 67cc71c..564ba2e 100644
--- a/pub/usage/pubspec.yaml
+++ b/pub/usage/pubspec.yaml
@@ -3,13 +3,13 @@
 # BSD-style license that can be found in the LICENSE file.
 
 name: usage
-version: 3.0.1
+version: 3.3.0
 description: A Google Analytics wrapper for both command-line, web, and Flutter apps.
 homepage: https://github.com/dart-lang/usage
 author: Dart Team <misc@dartlang.org>
 
 environment:
-  sdk: '>=1.19.0 <2.0.0'
+  sdk: '>=1.24.0 <2.0.0'
 
 dependencies:
   path: ^1.4.0
diff --git a/pub/usage/readme.md b/pub/usage/readme.md
index 458c581..931f91f 100644
--- a/pub/usage/readme.md
+++ b/pub/usage/readme.md
@@ -1,7 +1,6 @@
 # usage
 
-`usage` is a wrapper around Google Analytics for both command-line, web, and
-Flutter apps.
+`usage` is a wrapper around Google Analytics for command-line, web, and Flutter apps.
 
 [![pub package](https://img.shields.io/pub/v/usage.svg)](https://pub.dartlang.org/packages/usage)
 [![Build Status](https://travis-ci.org/dart-lang/usage.svg)](https://travis-ci.org/dart-lang/usage)
@@ -53,9 +52,15 @@
 something like:
 
 ```dart
-analytics.waitForLastPing(timeout: new Duration(milliseconds: 500)).then((_) {
-  exit(0);
-});
+await analytics.waitForLastPing(timeout: new Duration(milliseconds: 200));
+analytics.close();
+```
+
+or:
+
+```dart
+await analytics.waitForLastPing(timeout: new Duration(milliseconds: 200));
+exit(0);
 ```
 
 ## Using the API
@@ -111,6 +116,10 @@
 For more information, please see the Google Analytics Measurement Protocol
 [Policy](https://developers.google.com/analytics/devguides/collection/protocol/policy).
 
+## Contributing
+
+Tests can be run using `pub run test`.
+
 ## Issues and bugs
 
 Please file reports on the
diff --git a/pub/vector_math/BUILD.gn b/pub/vector_math/BUILD.gn
index 3136ecc..bc528bd 100644
--- a/pub/vector_math/BUILD.gn
+++ b/pub/vector_math/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for vector_math-2.0.4
+# This file is generated by importer.py for vector_math-2.0.5
 
 import("//build/dart/dart_package.gni")
 
diff --git a/pub/vector_math/analysis_options.yaml b/pub/vector_math/analysis_options.yaml
new file mode 100644
index 0000000..3ab0961
--- /dev/null
+++ b/pub/vector_math/analysis_options.yaml
@@ -0,0 +1,4 @@
+analyzer:
+  strong-mode:
+    implicit-dynamic: False
+    implicit-casts: False
\ No newline at end of file
diff --git a/pub/vector_math/benchmark/matrix_bench.dart b/pub/vector_math/benchmark/matrix_bench.dart
index efbfc32..bdb45e9 100644
--- a/pub/vector_math/benchmark/matrix_bench.dart
+++ b/pub/vector_math/benchmark/matrix_bench.dart
@@ -19,6 +19,7 @@
     new MatrixMultiplyBenchmark().report();
   }
 
+  @override
   void run() {
     for (int i = 0; i < 200; i++) {
       Matrix44Operations.multiply(C, 0, A, 0, B, 0);
@@ -36,6 +37,7 @@
     new SIMDMatrixMultiplyBenchmark().report();
   }
 
+  @override
   void run() {
     for (int i = 0; i < 200; i++) {
       Matrix44SIMDOperations.multiply(C, 0, A, 0, B, 0);
@@ -53,6 +55,7 @@
     new VectorTransformBenchmark().report();
   }
 
+  @override
   void run() {
     for (int i = 0; i < 200; i++) {
       Matrix44Operations.transform4(C, 0, A, 0, B, 0);
@@ -70,6 +73,7 @@
     new SIMDVectorTransformBenchmark().report();
   }
 
+  @override
   void run() {
     for (int i = 0; i < 200; i++) {
       Matrix44SIMDOperations.transform4(C, 0, A, 0, B, 0);
@@ -89,6 +93,7 @@
     new ViewMatrixBenchmark().report();
   }
 
+  @override
   void run() {
     for (int i = 0; i < 100; i++) {
       setViewMatrix(M, P, F, U);
@@ -96,7 +101,7 @@
   }
 }
 
-main() {
+void main() {
   MatrixMultiplyBenchmark.main();
   SIMDMatrixMultiplyBenchmark.main();
   VectorTransformBenchmark.main();
diff --git a/pub/vector_math/bin/mesh_generator.dart b/pub/vector_math/bin/mesh_generator.dart
index 208591b..fefb449 100644
--- a/pub/vector_math/bin/mesh_generator.dart
+++ b/pub/vector_math/bin/mesh_generator.dart
@@ -7,63 +7,59 @@
 import 'dart:convert';
 import 'package:vector_math/vector_math_geometry.dart';
 
+typedef MeshGeometry GenerateFunction(List<String> args);
+
 MeshGeometry generateCube(List<String> args) {
   if (args.length != 3) {
     return null;
   }
-  num width = double.parse(args[0]);
-  num height = double.parse(args[1]);
-  num depth = double.parse(args[2]);
-  var generator = new CubeGenerator();
-  MeshGeometry geometry = generator.createCube(width, height, depth);
-  return geometry;
+  final double width = double.parse(args[0]);
+  final double height = double.parse(args[1]);
+  final double depth = double.parse(args[2]);
+  final CubeGenerator generator = new CubeGenerator();
+  return generator.createCube(width, height, depth);
 }
 
 MeshGeometry generateSphere(List<String> args) {
   if (args.length != 1) {
     return null;
   }
-  num radius = double.parse(args[0]);
-  var generator = new SphereGenerator();
-  MeshGeometry geometry = generator.createSphere(radius);
-  return geometry;
+  final double radius = double.parse(args[0]);
+  final SphereGenerator generator = new SphereGenerator();
+  return generator.createSphere(radius);
 }
 
 MeshGeometry generateCircle(List<String> args) {
   if (args.length != 1) {
     return null;
   }
-  num radius = double.parse(args[0]);
-  var generator = new CircleGenerator();
-  MeshGeometry geometry = generator.createCircle(radius);
-  return geometry;
+  final double radius = double.parse(args[0]);
+  final CircleGenerator generator = new CircleGenerator();
+  return generator.createCircle(radius);
 }
 
 MeshGeometry generateCylinder(List<String> args) {
   if (args.length != 3) {
     return null;
   }
-  num topRadius = double.parse(args[0]);
-  num bottomRadius = double.parse(args[1]);
-  num height = double.parse(args[2]);
-  var generator = new CylinderGenerator();
-  MeshGeometry geometry =
-      generator.createCylinder(topRadius, bottomRadius, height);
-  return geometry;
+  final double topRadius = double.parse(args[0]);
+  final double bottomRadius = double.parse(args[1]);
+  final double height = double.parse(args[2]);
+  final CylinderGenerator generator = new CylinderGenerator();
+  return generator.createCylinder(topRadius, bottomRadius, height);
 }
 
 MeshGeometry generateRing(List<String> args) {
   if (args.length != 2) {
     return null;
   }
-  num innerRadius = double.parse(args[0]);
-  num outerRadius = double.parse(args[1]);
-  var generator = new RingGenerator();
-  MeshGeometry geometry = generator.createRing(innerRadius, outerRadius);
-  return geometry;
+  final double innerRadius = double.parse(args[0]);
+  final double outerRadius = double.parse(args[1]);
+  final RingGenerator generator = new RingGenerator();
+  return generator.createRing(innerRadius, outerRadius);
 }
 
-Map<String, Function> generators = {
+Map<String, GenerateFunction> generators = <String, GenerateFunction>{
   'cube': generateCube,
   'sphere': generateSphere,
   'circle': generateCircle,
@@ -71,10 +67,10 @@
   'ring': generateRing
 };
 
-main(List<String> args_) {
-  List<String> args = new List.from(args_, growable: true);
+void main(List<String> args_) {
+  final List<String> args = new List<String>.from(args_, growable: true);
 
-  if (args.length == 0) {
+  if (args.isEmpty) {
     print('mesh_generator.dart <type> [<arg0> ... <argN>]');
     print('');
     print('<type> = cube, sphere, cylinder');
@@ -86,13 +82,13 @@
     print('');
     return;
   }
-  var type = args.removeAt(0);
-  var generator = generators[type];
+  final String type = args.removeAt(0);
+  final GenerateFunction generator = generators[type];
   if (generator == null) {
     print('Could not find generator for $type');
     return;
   }
-  MeshGeometry geometry = generator(args);
+  final MeshGeometry geometry = generator(args);
   if (geometry == null) {
     print('Error generating geometry for $type');
     return;
diff --git a/pub/vector_math/changelog.md b/pub/vector_math/changelog.md
index 5122c85..d3da5d9 100644
--- a/pub/vector_math/changelog.md
+++ b/pub/vector_math/changelog.md
@@ -1,5 +1,9 @@
 # Changelog - vector_math
 
+## v 2.0.5 - July 2017
+
+- Strong mode clean
+
 ## v 2.0.4 - February 2017
 
 - Added Matrix4.isIdentity()
diff --git a/pub/vector_math/lib/hash.dart b/pub/vector_math/lib/hash.dart
index b355d2c..d5fbfb5 100644
--- a/pub/vector_math/lib/hash.dart
+++ b/pub/vector_math/lib/hash.dart
@@ -2,11 +2,11 @@
 // All rights reserved. Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-/**
- * Generates a hash code for multiple [objects].
- */
-int hashObjects(Iterable objects) =>
-    _finish(objects.fold(0, (h, i) => _combine(h, i.hashCode)));
+///
+/// Generates a hash code for multiple [objects].
+///
+int hashObjects(Iterable<Object> objects) =>
+    _finish(objects.fold<int>(0, (int h, Object i) => _combine(h, i.hashCode)));
 
 // Jenkins hash functions
 int _combine(int hash, int value) {
diff --git a/pub/vector_math/lib/src/vector_math/aabb2.dart b/pub/vector_math/lib/src/vector_math/aabb2.dart
index cc50ae8..1039aa4 100644
--- a/pub/vector_math/lib/src/vector_math/aabb2.dart
+++ b/pub/vector_math/lib/src/vector_math/aabb2.dart
@@ -78,8 +78,8 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix3 t) {
-    final center = new Vector2.zero();
-    final halfExtents = new Vector2.zero();
+    final Vector2 center = new Vector2.zero();
+    final Vector2 halfExtents = new Vector2.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t
       ..transform2(center)
@@ -94,8 +94,8 @@
 
   /// Rotate [this] by the rotation matrix [t].
   void rotate(Matrix3 t) {
-    final center = new Vector2.zero();
-    final halfExtents = new Vector2.zero();
+    final Vector2 center = new Vector2.zero();
+    final Vector2 halfExtents = new Vector2.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t.absoluteRotate2(halfExtents);
     _min
@@ -133,8 +133,8 @@
 
   /// Return if [this] contains [other].
   bool containsAabb2(Aabb2 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector2 otherMax = other._max;
+    final Vector2 otherMin = other._min;
 
     return (_min.x < otherMin.x) &&
         (_min.y < otherMin.y) &&
@@ -143,17 +143,16 @@
   }
 
   /// Return if [this] contains [other].
-  bool containsVector2(Vector2 other) {
-    return (_min.x < other.x) &&
-        (_min.y < other.y) &&
-        (_max.x > other.x) &&
-        (_max.y > other.y);
-  }
+  bool containsVector2(Vector2 other) =>
+      (_min.x < other.x) &&
+      (_min.y < other.y) &&
+      (_max.x > other.x) &&
+      (_max.y > other.y);
 
   /// Return if [this] intersects with [other].
   bool intersectsWithAabb2(Aabb2 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector2 otherMax = other._max;
+    final Vector2 otherMin = other._min;
 
     return (_min.x <= otherMax.x) &&
         (_min.y <= otherMax.y) &&
@@ -162,10 +161,9 @@
   }
 
   /// Return if [this] intersects with [other].
-  bool intersectsWithVector2(Vector2 other) {
-    return (_min.x <= other.x) &&
-        (_min.y <= other.y) &&
-        (_max.x >= other.x) &&
-        (_max.y >= other.y);
-  }
+  bool intersectsWithVector2(Vector2 other) =>
+      (_min.x <= other.x) &&
+      (_min.y <= other.y) &&
+      (_max.x >= other.x) &&
+      (_max.y >= other.y);
 }
diff --git a/pub/vector_math/lib/src/vector_math/aabb3.dart b/pub/vector_math/lib/src/vector_math/aabb3.dart
index d9021e5..c7c1488 100644
--- a/pub/vector_math/lib/src/vector_math/aabb3.dart
+++ b/pub/vector_math/lib/src/vector_math/aabb3.dart
@@ -86,46 +86,46 @@
   /// Set the AABB to enclose a [triangle].
   void setTriangle(Triangle triangle) {
     _min.setValues(
-        Math.min(triangle._point0.x,
-            Math.min(triangle._point1.x, triangle._point2.x)),
-        Math.min(triangle._point0.y,
-            Math.min(triangle._point1.y, triangle._point2.y)),
-        Math.min(triangle._point0.z,
-            Math.min(triangle._point1.z, triangle._point2.z)));
+        math.min(triangle._point0.x,
+            math.min(triangle._point1.x, triangle._point2.x)),
+        math.min(triangle._point0.y,
+            math.min(triangle._point1.y, triangle._point2.y)),
+        math.min(triangle._point0.z,
+            math.min(triangle._point1.z, triangle._point2.z)));
     _max.setValues(
-        Math.max(triangle._point0.x,
-            Math.max(triangle._point1.x, triangle._point2.x)),
-        Math.max(triangle._point0.y,
-            Math.max(triangle._point1.y, triangle._point2.y)),
-        Math.max(triangle._point0.z,
-            Math.max(triangle._point1.z, triangle._point2.z)));
+        math.max(triangle._point0.x,
+            math.max(triangle._point1.x, triangle._point2.x)),
+        math.max(triangle._point0.y,
+            math.max(triangle._point1.y, triangle._point2.y)),
+        math.max(triangle._point0.z,
+            math.max(triangle._point1.z, triangle._point2.z)));
   }
 
   /// Set the AABB to enclose a [quad].
   void setQuad(Quad quad) {
     _min.setValues(
-        Math.min(quad._point0.x,
-            Math.min(quad._point1.x, Math.min(quad._point2.x, quad._point3.x))),
-        Math.min(quad._point0.y,
-            Math.min(quad._point1.y, Math.min(quad._point2.y, quad._point3.y))),
-        Math.min(
+        math.min(quad._point0.x,
+            math.min(quad._point1.x, math.min(quad._point2.x, quad._point3.x))),
+        math.min(quad._point0.y,
+            math.min(quad._point1.y, math.min(quad._point2.y, quad._point3.y))),
+        math.min(
             quad._point0.z,
-            Math.min(
-                quad._point1.z, Math.min(quad._point2.z, quad._point3.z))));
+            math.min(
+                quad._point1.z, math.min(quad._point2.z, quad._point3.z))));
     _max.setValues(
-        Math.max(quad._point0.x,
-            Math.max(quad._point1.x, Math.max(quad._point2.x, quad._point3.x))),
-        Math.max(quad._point0.y,
-            Math.max(quad._point1.y, Math.max(quad._point2.y, quad._point3.y))),
-        Math.max(
+        math.max(quad._point0.x,
+            math.max(quad._point1.x, math.max(quad._point2.x, quad._point3.x))),
+        math.max(quad._point0.y,
+            math.max(quad._point1.y, math.max(quad._point2.y, quad._point3.y))),
+        math.max(
             quad._point0.z,
-            Math.max(
-                quad._point1.z, Math.max(quad._point2.z, quad._point3.z))));
+            math.max(
+                quad._point1.z, math.max(quad._point2.z, quad._point3.z))));
   }
 
   /// Set the AABB to enclose a [obb].
   void setObb3(Obb3 obb) {
-    final corner = new Vector3.zero();
+    final Vector3 corner = new Vector3.zero();
 
     obb.copyCorner(0, corner);
     _min.setFrom(corner);
@@ -156,23 +156,22 @@
   /// Set the AABB to enclose a limited [ray] (or line segment) that is limited
   /// by [limitMin] and [limitMax].
   void setRay(Ray ray, double limitMin, double limitMax) {
-    ray.copyAt(_min, limitMin);
-    ray.copyAt(_max, limitMax);
+    ray..copyAt(_min, limitMin)..copyAt(_max, limitMax);
 
     if (_max.x < _min.x) {
-      final temp = _max.x;
+      final double temp = _max.x;
       _max.x = _min.x;
       _min.x = temp;
     }
 
     if (_max.y < _min.y) {
-      final temp = _max.y;
+      final double temp = _max.y;
       _max.y = _min.y;
       _min.y = temp;
     }
 
     if (_max.z < _min.z) {
-      final temp = _max.z;
+      final double temp = _max.z;
       _max.z = _min.z;
       _min.z = temp;
     }
@@ -206,8 +205,8 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    final center = new Vector3.zero();
-    final halfExtents = new Vector3.zero();
+    final Vector3 center = new Vector3.zero();
+    final Vector3 halfExtents = new Vector3.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t
       ..transform3(center)
@@ -222,8 +221,8 @@
 
   /// Rotate [this] by the rotation matrix [t].
   void rotate(Matrix4 t) {
-    final center = new Vector3.zero();
-    final halfExtents = new Vector3.zero();
+    final Vector3 center = new Vector3.zero();
+    final Vector3 halfExtents = new Vector3.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t.absoluteRotate(halfExtents);
     _min
@@ -287,8 +286,8 @@
 
   /// Return if [this] contains [other].
   bool containsAabb3(Aabb3 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector3 otherMax = other._max;
+    final Vector3 otherMin = other._min;
 
     return (_min.x < otherMin.x) &&
         (_min.y < otherMin.y) &&
@@ -300,21 +299,21 @@
 
   /// Return if [this] contains [other].
   bool containsSphere(Sphere other) {
-    final boxExtends = new Vector3.all(other._radius);
-    final sphereBox = new Aabb3.centerAndHalfExtents(other._center, boxExtends);
+    final Vector3 boxExtends = new Vector3.all(other._radius);
+    final Aabb3 sphereBox =
+        new Aabb3.centerAndHalfExtents(other._center, boxExtends);
 
     return containsAabb3(sphereBox);
   }
 
   /// Return if [this] contains [other].
-  bool containsVector3(Vector3 other) {
-    return (_min.x < other.x) &&
-        (_min.y < other.y) &&
-        (_min.z < other.z) &&
-        (_max.x > other.x) &&
-        (_max.y > other.y) &&
-        (_max.z > other.z);
-  }
+  bool containsVector3(Vector3 other) =>
+      (_min.x < other.x) &&
+      (_min.y < other.y) &&
+      (_min.z < other.z) &&
+      (_max.x > other.x) &&
+      (_max.y > other.y) &&
+      (_max.z > other.z);
 
   /// Return if [this] contains [other].
   bool containsTriangle(Triangle other) =>
@@ -324,8 +323,8 @@
 
   /// Return if [this] intersects with [other].
   bool intersectsWithAabb3(Aabb3 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector3 otherMax = other._max;
+    final Vector3 otherMin = other._min;
 
     return (_min.x <= otherMax.x) &&
         (_min.y <= otherMax.y) &&
@@ -337,12 +336,12 @@
 
   /// Return if [this] intersects with [other].
   bool intersectsWithSphere(Sphere other) {
-    final center = other._center;
-    final radius = other._radius;
-    var d = 0.0;
-    var e = 0.0;
+    final Vector3 center = other._center;
+    final double radius = other._radius;
+    double d = 0.0;
+    double e = 0.0;
 
-    for (var i = 0; i < 3; ++i) {
+    for (int i = 0; i < 3; ++i) {
       if ((e = center[i] - _min[i]) < 0.0) {
         if (e < -radius) {
           return false;
@@ -364,29 +363,28 @@
   }
 
   /// Return if [this] intersects with [other].
-  bool intersectsWithVector3(Vector3 other) {
-    return (_min.x <= other.x) &&
-        (_min.y <= other.y) &&
-        (_min.z <= other.z) &&
-        (_max.x >= other.x) &&
-        (_max.y >= other.y) &&
-        (_max.z >= other.z);
-  }
+  bool intersectsWithVector3(Vector3 other) =>
+      (_min.x <= other.x) &&
+      (_min.y <= other.y) &&
+      (_min.z <= other.z) &&
+      (_max.x >= other.x) &&
+      (_max.y >= other.y) &&
+      (_max.z >= other.z);
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _aabbCenter = new Vector3.zero();
-  static final _aabbHalfExtents = new Vector3.zero();
-  static final _v0 = new Vector3.zero();
-  static final _v1 = new Vector3.zero();
-  static final _v2 = new Vector3.zero();
-  static final _f0 = new Vector3.zero();
-  static final _f1 = new Vector3.zero();
-  static final _f2 = new Vector3.zero();
-  static final _trianglePlane = new Plane();
+  static final Vector3 _aabbCenter = new Vector3.zero();
+  static final Vector3 _aabbHalfExtents = new Vector3.zero();
+  static final Vector3 _v0 = new Vector3.zero();
+  static final Vector3 _v1 = new Vector3.zero();
+  static final Vector3 _v2 = new Vector3.zero();
+  static final Vector3 _f0 = new Vector3.zero();
+  static final Vector3 _f1 = new Vector3.zero();
+  static final Vector3 _f2 = new Vector3.zero();
+  static final Plane _trianglePlane = new Plane();
 
-  static final _u0 = new Vector3(1.0, 0.0, 0.0);
-  static final _u1 = new Vector3(0.0, 1.0, 0.0);
-  static final _u2 = new Vector3(0.0, 0.0, 1.0);
+  static final Vector3 _u0 = new Vector3(1.0, 0.0, 0.0);
+  static final Vector3 _u1 = new Vector3(0.0, 1.0, 0.0);
+  static final Vector3 _u2 = new Vector3(0.0, 0.0, 1.0);
 
   /// Return if [this] intersects with [other].
   /// [epsilon] allows the caller to specify a custum eplsilon value that should
@@ -432,11 +430,11 @@
       p0 = _v0.z * _f0.y - _v0.y * _f0.z;
       p2 = _v2.z * _f0.y - _v2.y * _f0.z;
       r = _aabbHalfExtents[1] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.y.abs();
-      if (Math.max(-Math.max(p0, p2), Math.min(p0, p2)) > r + epsilon) {
+      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p2) - r;
+      a = math.min(p0, p2) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u0.crossInto(_f0, result.axis);
@@ -450,11 +448,11 @@
       p0 = _v0.z * _f1.y - _v0.y * _f1.z;
       p1 = _v1.z * _f1.y - _v1.y * _f1.z;
       r = _aabbHalfExtents[1] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.y.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u0.crossInto(_f1, result.axis);
@@ -468,11 +466,11 @@
       p0 = _v0.z * _f2.y - _v0.y * _f2.z;
       p1 = _v1.z * _f2.y - _v1.y * _f2.z;
       r = _aabbHalfExtents[1] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.y.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u0.crossInto(_f2, result.axis);
@@ -486,11 +484,11 @@
       p0 = _v0.x * _f0.z - _v0.z * _f0.x;
       p2 = _v2.x * _f0.z - _v2.z * _f0.x;
       r = _aabbHalfExtents[0] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.x.abs();
-      if (Math.max(-Math.max(p0, p2), Math.min(p0, p2)) > r + epsilon) {
+      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p2) - r;
+      a = math.min(p0, p2) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u1.crossInto(_f0, result.axis);
@@ -504,11 +502,11 @@
       p0 = _v0.x * _f1.z - _v0.z * _f1.x;
       p1 = _v1.x * _f1.z - _v1.z * _f1.x;
       r = _aabbHalfExtents[0] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u1.crossInto(_f1, result.axis);
@@ -522,11 +520,11 @@
       p0 = _v0.x * _f2.z - _v0.z * _f2.x;
       p1 = _v1.x * _f2.z - _v1.z * _f2.x;
       r = _aabbHalfExtents[0] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u1.crossInto(_f2, result.axis);
@@ -540,11 +538,11 @@
       p0 = _v0.y * _f0.x - _v0.x * _f0.y;
       p2 = _v2.y * _f0.x - _v2.x * _f0.y;
       r = _aabbHalfExtents[0] * _f0.y.abs() + _aabbHalfExtents[1] * _f0.x.abs();
-      if (Math.max(-Math.max(p0, p2), Math.min(p0, p2)) > r + epsilon) {
+      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p2) - r;
+      a = math.min(p0, p2) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u2.crossInto(_f0, result.axis);
@@ -558,11 +556,11 @@
       p0 = _v0.y * _f1.x - _v0.x * _f1.y;
       p1 = _v1.y * _f1.x - _v1.x * _f1.y;
       r = _aabbHalfExtents[0] * _f1.y.abs() + _aabbHalfExtents[1] * _f1.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u2.crossInto(_f1, result.axis);
@@ -576,11 +574,11 @@
       p0 = _v0.y * _f2.x - _v0.x * _f2.y;
       p1 = _v1.y * _f2.x - _v1.x * _f2.y;
       r = _aabbHalfExtents[0] * _f2.y.abs() + _aabbHalfExtents[1] * _f2.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u2.crossInto(_f2, result.axis);
@@ -589,31 +587,31 @@
 
     // Test the three axes corresponding to the face normals of AABB b (category 1). // Exit if...
     // ... [-e0, e0] and [min(v0.x,v1.x,v2.x), max(v0.x,v1.x,v2.x)] do not overlap
-    if (Math.max(_v0.x, Math.max(_v1.x, _v2.x)) < -_aabbHalfExtents[0] ||
-        Math.min(_v0.x, Math.min(_v1.x, _v2.x)) > _aabbHalfExtents[0]) {
+    if (math.max(_v0.x, math.max(_v1.x, _v2.x)) < -_aabbHalfExtents[0] ||
+        math.min(_v0.x, math.min(_v1.x, _v2.x)) > _aabbHalfExtents[0]) {
       return false;
     }
-    a = Math.min(_v0.x, Math.min(_v1.x, _v2.x)) - _aabbHalfExtents[0];
+    a = math.min(_v0.x, math.min(_v1.x, _v2.x)) - _aabbHalfExtents[0];
     if (result != null && (result._depth == null || result._depth < a)) {
       result._depth = a;
       result.axis.setFrom(_u0);
     }
     // ... [-e1, e1] and [min(v0.y,v1.y,v2.y), max(v0.y,v1.y,v2.y)] do not overlap
-    if (Math.max(_v0.y, Math.max(_v1.y, _v2.y)) < -_aabbHalfExtents[1] ||
-        Math.min(_v0.y, Math.min(_v1.y, _v2.y)) > _aabbHalfExtents[1]) {
+    if (math.max(_v0.y, math.max(_v1.y, _v2.y)) < -_aabbHalfExtents[1] ||
+        math.min(_v0.y, math.min(_v1.y, _v2.y)) > _aabbHalfExtents[1]) {
       return false;
     }
-    a = Math.min(_v0.y, Math.min(_v1.y, _v2.y)) - _aabbHalfExtents[1];
+    a = math.min(_v0.y, math.min(_v1.y, _v2.y)) - _aabbHalfExtents[1];
     if (result != null && (result._depth == null || result._depth < a)) {
       result._depth = a;
       result.axis.setFrom(_u1);
     }
     // ... [-e2, e2] and [min(v0.z,v1.z,v2.z), max(v0.z,v1.z,v2.z)] do not overlap
-    if (Math.max(_v0.z, Math.max(_v1.z, _v2.z)) < -_aabbHalfExtents[2] ||
-        Math.min(_v0.z, Math.min(_v1.z, _v2.z)) > _aabbHalfExtents[2]) {
+    if (math.max(_v0.z, math.max(_v1.z, _v2.z)) < -_aabbHalfExtents[2] ||
+        math.min(_v0.z, math.min(_v1.z, _v2.z)) > _aabbHalfExtents[2]) {
       return false;
     }
-    a = Math.min(_v0.z, Math.min(_v1.z, _v2.z)) - _aabbHalfExtents[2];
+    a = math.min(_v0.z, math.min(_v1.z, _v2.z)) - _aabbHalfExtents[2];
     if (result != null && (result._depth == null || result._depth < a)) {
       result._depth = a;
       result.axis.setFrom(_u2);
@@ -635,14 +633,14 @@
     copyCenterAndHalfExtents(_aabbCenter, _aabbHalfExtents);
 
     // Compute the projection interval radius of b onto L(t) = b.c + t * p.n
-    double r = _aabbHalfExtents[0] * other.normal[0].abs() +
+    final double r = _aabbHalfExtents[0] * other.normal[0].abs() +
         _aabbHalfExtents[1] * other.normal[1].abs() +
         _aabbHalfExtents[2] * other.normal[2].abs();
     // Compute distance of box center from plane
-    double s = other.normal.dot(_aabbCenter) - other.constant;
+    final double s = other.normal.dot(_aabbCenter) - other.constant;
     // Intersection occurs when distance s falls within [-r,+r] interval
     if (s.abs() <= r) {
-      final a = s - r;
+      final double a = s - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         result.axis.setFrom(other.normal);
@@ -654,8 +652,8 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _quadTriangle0 = new Triangle();
-  static final _quadTriangle1 = new Triangle();
+  static final Triangle _quadTriangle0 = new Triangle();
+  static final Triangle _quadTriangle1 = new Triangle();
 
   /// Return if [this] intersects with [other].
   /// [epsilon] allows the caller to specify a custum eplsilon value that should
diff --git a/pub/vector_math/lib/src/vector_math/colors.dart b/pub/vector_math/lib/src/vector_math/colors.dart
index 6b5a533..ff6a7d6 100644
--- a/pub/vector_math/lib/src/vector_math/colors.dart
+++ b/pub/vector_math/lib/src/vector_math/colors.dart
@@ -8,10 +8,10 @@
 /// manipulating colors. In addition to that, some known colors can be accessed
 /// for fast prototyping.
 class Colors {
-  static final _hexStringFullRegex = new RegExp(
+  static final RegExp _hexStringFullRegex = new RegExp(
       r'\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})(?:([0-9a-f]{2}))?',
       caseSensitive: false);
-  static final _hexStringSmallRegex = new RegExp(
+  static final RegExp _hexStringSmallRegex = new RegExp(
       r'\#?([0-9a-f])([0-9a-f])([0-9a-f])(?:([0-9a-f]))?',
       caseSensitive: false);
 
@@ -26,42 +26,42 @@
   /// corresponding color value and store it in [result]. The first group is
   /// treated as the alpha channel if a [value] with four groups is passed.
   static void fromHexString(String value, Vector4 result) {
-    final fullMatch = _hexStringFullRegex.matchAsPrefix(value);
+    final Match fullMatch = _hexStringFullRegex.matchAsPrefix(value);
 
     if (fullMatch != null) {
       if (fullMatch[4] == null) {
-        final r = int.parse(fullMatch[1], radix: 16);
-        final g = int.parse(fullMatch[2], radix: 16);
-        final b = int.parse(fullMatch[3], radix: 16);
+        final int r = int.parse(fullMatch[1], radix: 16);
+        final int g = int.parse(fullMatch[2], radix: 16);
+        final int b = int.parse(fullMatch[3], radix: 16);
 
         fromRgba(r, g, b, 255, result);
         return;
       } else {
-        final a = int.parse(fullMatch[1], radix: 16);
-        final r = int.parse(fullMatch[2], radix: 16);
-        final g = int.parse(fullMatch[3], radix: 16);
-        final b = int.parse(fullMatch[4], radix: 16);
+        final int a = int.parse(fullMatch[1], radix: 16);
+        final int r = int.parse(fullMatch[2], radix: 16);
+        final int g = int.parse(fullMatch[3], radix: 16);
+        final int b = int.parse(fullMatch[4], radix: 16);
 
         fromRgba(r, g, b, a, result);
         return;
       }
     }
 
-    final smallMatch = _hexStringSmallRegex.matchAsPrefix(value);
+    final Match smallMatch = _hexStringSmallRegex.matchAsPrefix(value);
 
     if (smallMatch != null) {
       if (smallMatch[4] == null) {
-        final r = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
-        final g = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
-        final b = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
+        final int r = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
+        final int g = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
+        final int b = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
 
         fromRgba(r, g, b, 255, result);
         return;
       } else {
-        final a = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
-        final r = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
-        final g = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
-        final b = int.parse(smallMatch[4] + smallMatch[4], radix: 16);
+        final int a = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
+        final int r = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
+        final int g = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
+        final int b = int.parse(smallMatch[4] + smallMatch[4], radix: 16);
 
         fromRgba(r, g, b, a, result);
         return;
@@ -77,25 +77,25 @@
   /// (default false).
   static String toHexString(Vector4 input,
       {bool alpha: false, bool short: false}) {
-    final r = (input.r * 0xFF).floor() & 0xFF;
-    final g = (input.g * 0xFF).floor() & 0xFF;
-    final b = (input.b * 0xFF).floor() & 0xFF;
-    final a = (input.a * 0xFF).floor() & 0xFF;
+    final int r = (input.r * 0xFF).floor() & 0xFF;
+    final int g = (input.g * 0xFF).floor() & 0xFF;
+    final int b = (input.b * 0xFF).floor() & 0xFF;
+    final int a = (input.a * 0xFF).floor() & 0xFF;
 
-    final isShort = short &&
+    final bool isShort = short &&
         ((r >> 4) == (r & 0xF)) &&
         ((g >> 4) == (g & 0xF)) &&
         ((b >> 4) == (b & 0xF)) &&
         (!alpha || (a >> 4) == (a & 0xF));
 
     if (isShort) {
-      final rgb = (r & 0xF).toRadixString(16) +
+      final String rgb = (r & 0xF).toRadixString(16) +
           (g & 0xF).toRadixString(16) +
           (b & 0xF).toRadixString(16);
 
       return alpha ? (a & 0xF).toRadixString(16) + rgb : rgb;
     } else {
-      final rgb = r.toRadixString(16).padLeft(2, '0') +
+      final String rgb = r.toRadixString(16).padLeft(2, '0') +
           g.toRadixString(16).padLeft(2, '0') +
           b.toRadixString(16).padLeft(2, '0');
 
@@ -107,16 +107,16 @@
   /// in [result].
   static void alphaBlend(
       Vector4 foreground, Vector4 background, Vector4 result) {
-    final a = foreground.a + (1.0 - foreground.a) * background.a;
-    final factor = 1.0 / a;
+    final double a = foreground.a + (1.0 - foreground.a) * background.a;
+    final double factor = 1.0 / a;
 
-    final r = factor *
+    final double r = factor *
         (foreground.a * foreground.r +
             (1.0 - foreground.a) * background.a * background.r);
-    final g = factor *
+    final double g = factor *
         (foreground.a * foreground.g +
             (1.0 - foreground.a) * background.a * background.g);
-    final b = factor *
+    final double b = factor *
         (foreground.a * foreground.b +
             (1.0 - foreground.a) * background.a * background.b);
 
@@ -125,7 +125,7 @@
 
   /// Convert a [input] color to a gray scaled color and store it in [result].
   static void toGrayscale(Vector4 input, Vector4 result) {
-    final value = 0.21 * input.r + 0.71 * input.g + 0.07 * input.b;
+    final double value = 0.21 * input.r + 0.71 * input.g + 0.07 * input.b;
 
     result
       ..r = value
@@ -139,12 +139,12 @@
   /// the default value is 2.2.
   static void linearToGamma(Vector4 linearColor, Vector4 gammaColor,
       [double gamma = 2.2]) {
-    final exponent = 1.0 / gamma;
+    final double exponent = 1.0 / gamma;
 
     gammaColor
-      ..r = Math.pow(linearColor.r, exponent)
-      ..g = Math.pow(linearColor.g, exponent)
-      ..b = Math.pow(linearColor.b, exponent)
+      ..r = math.pow(linearColor.r, exponent).toDouble()
+      ..g = math.pow(linearColor.g, exponent).toDouble()
+      ..b = math.pow(linearColor.b, exponent).toDouble()
       ..a = linearColor.a;
   }
 
@@ -154,21 +154,21 @@
   static void gammaToLinear(Vector4 gammaColor, Vector4 linearColor,
       [double gamma = 2.2]) {
     linearColor
-      ..r = Math.pow(gammaColor.r, gamma)
-      ..g = Math.pow(gammaColor.g, gamma)
-      ..b = Math.pow(gammaColor.b, gamma)
+      ..r = math.pow(gammaColor.r, gamma).toDouble()
+      ..g = math.pow(gammaColor.g, gamma).toDouble()
+      ..b = math.pow(gammaColor.b, gamma).toDouble()
       ..a = gammaColor.a;
   }
 
   /// Convert [rgbColor] from rgb color model to the hue, saturation, and value
   /// (HSV) color model and store it in [hsvColor].
   static void rgbToHsv(Vector4 rgbColor, Vector4 hsvColor) {
-    final max = Math.max(Math.max(rgbColor.r, rgbColor.g), rgbColor.b);
-    final min = Math.min(Math.min(rgbColor.r, rgbColor.g), rgbColor.b);
-    final d = max - min;
-    final v = max;
-    final s = max == 0.0 ? 0.0 : d / max;
-    var h = 0.0;
+    final double max = math.max(math.max(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double min = math.min(math.min(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double d = max - min;
+    final double v = max;
+    final double s = max == 0.0 ? 0.0 : d / max;
+    double h = 0.0;
 
     if (max != min) {
       if (max == rgbColor.r) {
@@ -189,11 +189,11 @@
   /// Convert [hsvColor] from hue, saturation, and value (HSV) color model to
   /// the RGB color model and store it in [rgbColor].
   static void hsvToRgb(Vector4 hsvColor, Vector4 rgbColor) {
-    final i = (hsvColor.x * 6.0).floor();
-    final f = hsvColor.x * 6.0 - i.toDouble();
-    final p = hsvColor.z * (1.0 - hsvColor.y);
-    final q = hsvColor.z * (1.0 - f * hsvColor.y);
-    final t = hsvColor.z * (1.0 - (1.0 - f) * hsvColor.y);
+    final int i = (hsvColor.x * 6.0).floor();
+    final double f = hsvColor.x * 6.0 - i.toDouble();
+    final double p = hsvColor.z * (1.0 - hsvColor.y);
+    final double q = hsvColor.z * (1.0 - f * hsvColor.y);
+    final double t = hsvColor.z * (1.0 - (1.0 - f) * hsvColor.y);
 
     switch (i % 6) {
       case 0:
@@ -220,14 +220,14 @@
   /// Convert [rgbColor] from rgb color model to the hue, saturation, and
   /// lightness (HSL) color model and store it in [hslColor].
   static void rgbToHsl(Vector4 rgbColor, Vector4 hslColor) {
-    final max = Math.max(Math.max(rgbColor.r, rgbColor.g), rgbColor.b);
-    final min = Math.min(Math.min(rgbColor.r, rgbColor.g), rgbColor.b);
-    final l = (max + min) / 2.0;
-    var h = 0.0;
-    var s = 0.0;
+    final double max = math.max(math.max(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double min = math.min(math.min(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double l = (max + min) / 2.0;
+    double h = 0.0;
+    double s = 0.0;
 
     if (max != min) {
-      final d = max - min;
+      final double d = max - min;
 
       s = l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
 
@@ -252,14 +252,14 @@
     if (hslColor.y == 0.0) {
       rgbColor.setValues(hslColor.z, hslColor.z, hslColor.z, hslColor.a);
     } else {
-      final q = hslColor.z < 0.5
+      final double q = hslColor.z < 0.5
           ? hslColor.z * (1.0 + hslColor.y)
           : hslColor.z + hslColor.y - hslColor.z * hslColor.y;
-      final p = 2.0 * hslColor.z - q;
+      final double p = 2.0 * hslColor.z - q;
 
-      final r = _hueToRgb(p, q, hslColor.x + 1.0 / 3.0);
-      final g = _hueToRgb(p, q, hslColor.x);
-      final b = _hueToRgb(p, q, hslColor.x - 1.0 / 3.0);
+      final double r = _hueToRgb(p, q, hslColor.x + 1.0 / 3.0);
+      final double g = _hueToRgb(p, q, hslColor.x);
+      final double b = _hueToRgb(p, q, hslColor.x - 1.0 / 3.0);
 
       rgbColor.setValues(r, g, b, hslColor.a);
     }
diff --git a/pub/vector_math/lib/src/vector_math/constants.dart b/pub/vector_math/lib/src/vector_math/constants.dart
index 3056dc1..e2c2840 100644
--- a/pub/vector_math/lib/src/vector_math/constants.dart
+++ b/pub/vector_math/lib/src/vector_math/constants.dart
@@ -5,7 +5,7 @@
 part of vector_math;
 
 /// Constant factor to convert and angle from degrees to radians.
-const double degrees2Radians = Math.PI / 180.0;
+const double degrees2Radians = math.PI / 180.0;
 
 /// Constant factor to convert and angle from radians to degrees.
-const double radians2Degrees = 180.0 / Math.PI;
+const double radians2Degrees = 180.0 / math.PI;
diff --git a/pub/vector_math/lib/src/vector_math/error_helpers.dart b/pub/vector_math/lib/src/vector_math/error_helpers.dart
index ad46fa4..f57ba9d 100644
--- a/pub/vector_math/lib/src/vector_math/error_helpers.dart
+++ b/pub/vector_math/lib/src/vector_math/error_helpers.dart
@@ -7,21 +7,23 @@
 /// Returns relative error between [calculated] and [correct].
 /// The type of [calculated] and [correct] must match and can
 /// be any vector, matrix, or quaternion.
-double relativeError(calculated, correct) {
+double relativeError(dynamic calculated, dynamic correct) {
   if (calculated is num && correct is num) {
-    double diff = (calculated - correct).abs();
+    final double diff = (calculated - correct).abs().toDouble();
     return diff / correct;
   }
+  // ignore: return_of_invalid_type
   return calculated.relativeError(correct);
 }
 
 /// Returns absolute error between [calculated] and [correct].
 /// The type of [calculated] and [correct] must match and can
 /// be any vector, matrix, or quaternion.
-double absoluteError(calculated, correct) {
+double absoluteError(dynamic calculated, dynamic correct) {
   if (calculated is num && correct is num) {
-    double diff = (calculated - correct).abs();
+    final double diff = (calculated - correct).abs().toDouble();
     return diff;
   }
+  // ignore: return_of_invalid_type
   return calculated.absoluteError(correct);
 }
diff --git a/pub/vector_math/lib/src/vector_math/frustum.dart b/pub/vector_math/lib/src/vector_math/frustum.dart
index 0e1ac8d..1154eb9 100644
--- a/pub/vector_math/lib/src/vector_math/frustum.dart
+++ b/pub/vector_math/lib/src/vector_math/frustum.dart
@@ -59,11 +59,11 @@
 
   /// Set [this] from [matrix].
   void setFromMatrix(Matrix4 matrix) {
-    var me = matrix.storage;
-    var me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
-    var me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
-    var me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
-    var me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
+    final Float32List me = matrix.storage;
+    final double me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
+    final double me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
+    final double me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
+    final double me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
 
     _plane0
       ..setFromComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12)
@@ -145,8 +145,8 @@
 
   /// Check if [this] intersects with [sphere].
   bool intersectsWithSphere(Sphere sphere) {
-    final negativeRadius = -sphere._radius;
-    final center = sphere.center;
+    final double negativeRadius = -sphere._radius;
+    final Vector3 center = sphere.center;
 
     if (_plane0.distanceToVector3(center) < negativeRadius) {
       return false;
@@ -197,7 +197,7 @@
   }
 
   bool _intersectsWithAabb3CheckPlane(Aabb3 aabb, Plane plane) {
-    var outPx, outPy, outPz, outNx, outNy, outNz;
+    double outPx, outPy, outPz, outNx, outNy, outNz;
 
     if (plane._normal.x < 0.0) {
       outPx = aabb.min.x;
@@ -223,11 +223,11 @@
       outNz = aabb.min.z;
     }
 
-    final d1 = plane._normal.x * outPx +
+    final double d1 = plane._normal.x * outPx +
         plane._normal.y * outPy +
         plane._normal.z * outPz +
         plane._constant;
-    final d2 = plane._normal.x * outNx +
+    final double d2 = plane._normal.x * outNx +
         plane._normal.y * outNy +
         plane._normal.z * outNz +
         plane._constant;
diff --git a/pub/vector_math/lib/src/vector_math/matrix2.dart b/pub/vector_math/lib/src/vector_math/matrix2.dart
index db46150..d02adff 100644
--- a/pub/vector_math/lib/src/vector_math/matrix2.dart
+++ b/pub/vector_math/lib/src/vector_math/matrix2.dart
@@ -26,8 +26,9 @@
       det = 1.0 / det;
     }
 
-    x.x = det * (a22 * bx - a12 * by);
-    x.y = det * (a11 * by - a21 * bx);
+    x
+      ..x = det * (a22 * bx - a12 * by)
+      ..y = det * (a11 * by - a21 * bx);
   }
 
   /// Return index in storage for [row], [col] value.
@@ -42,7 +43,7 @@
   }
 
   /// Set value at [row], [col] to be [v].
-  setEntry(int row, int col, double v) {
+  void setEntry(int row, int col, double v) {
     assert((row >= 0) && (row < dimension));
     assert((col >= 0) && (col < dimension));
 
@@ -54,10 +55,8 @@
       new Matrix2.zero()..setValues(arg0, arg1, arg2, arg3);
 
   /// New matrix from [values].
-  factory Matrix2.fromList(List<double> values) {
-    return new Matrix2.zero()
-      ..setValues(values[0], values[1], values[2], values[3]);
-  }
+  factory Matrix2.fromList(List<double> values) =>
+      new Matrix2.zero()..setValues(values[0], values[1], values[2], values[3]);
 
   /// Zero matrix.
   Matrix2.zero() : _m2storage = new Float32List(4);
@@ -90,8 +89,8 @@
 
   /// Sets the entire matrix to the column values.
   void setColumns(Vector2 arg0, Vector2 arg1) {
-    final arg0Storage = arg0._v2storage;
-    final arg1Storage = arg1._v2storage;
+    final Float32List arg0Storage = arg0._v2storage;
+    final Float32List arg1Storage = arg1._v2storage;
     _m2storage[0] = arg0Storage[0];
     _m2storage[1] = arg0Storage[1];
     _m2storage[2] = arg1Storage[0];
@@ -100,7 +99,7 @@
 
   /// Sets the entire matrix to the matrix in [arg].
   void setFrom(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float32List argStorage = arg._m2storage;
     _m2storage[3] = argStorage[3];
     _m2storage[2] = argStorage[2];
     _m2storage[1] = argStorage[1];
@@ -109,8 +108,8 @@
 
   /// Set [this] to the outer product of [u] and [v].
   void setOuter(Vector2 u, Vector2 v) {
-    final uStorage = u._v2storage;
-    final vStorage = v._v2storage;
+    final Float32List uStorage = u._v2storage;
+    final Float32List vStorage = v._v2storage;
     _m2storage[0] = uStorage[0] * vStorage[0];
     _m2storage[1] = uStorage[0] * vStorage[1];
     _m2storage[2] = uStorage[1] * vStorage[0];
@@ -125,12 +124,13 @@
 
   /// Sets the diagonal of the matrix to be [arg].
   void setDiagonal(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _m2storage[0] = argStorage[0];
     _m2storage[3] = argStorage[1];
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n';
 
   /// Dimension of the matrix.
@@ -145,14 +145,15 @@
   }
 
   /// Check if two matrices are the same.
-  bool operator ==(other) {
-    return (other is Matrix2) &&
-        (_m2storage[0] == other._m2storage[0]) &&
-        (_m2storage[1] == other._m2storage[1]) &&
-        (_m2storage[2] == other._m2storage[2]) &&
-        (_m2storage[3] == other._m2storage[3]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Matrix2) &&
+      (_m2storage[0] == other._m2storage[0]) &&
+      (_m2storage[1] == other._m2storage[1]) &&
+      (_m2storage[2] == other._m2storage[2]) &&
+      (_m2storage[3] == other._m2storage[3]);
 
+  @override
   int get hashCode => quiver.hashObjects(_m2storage);
 
   /// Returns row 0
@@ -169,15 +170,15 @@
 
   /// Sets [row] of the matrix to values in [arg]
   void setRow(int row, Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _m2storage[index(row, 0)] = argStorage[0];
     _m2storage[index(row, 1)] = argStorage[1];
   }
 
   /// Gets the [row] of the matrix
   Vector2 getRow(int row) {
-    final r = new Vector2.zero();
-    final rStorage = r._v2storage;
+    final Vector2 r = new Vector2.zero();
+    final Float32List rStorage = r._v2storage;
     rStorage[0] = _m2storage[index(row, 0)];
     rStorage[1] = _m2storage[index(row, 1)];
     return r;
@@ -185,17 +186,17 @@
 
   /// Assigns the [column] of the matrix [arg]
   void setColumn(int column, Vector2 arg) {
-    final argStorage = arg._v2storage;
-    final entry = column * 2;
+    final Float32List argStorage = arg._v2storage;
+    final int entry = column * 2;
     _m2storage[entry + 1] = argStorage[1];
     _m2storage[entry + 0] = argStorage[0];
   }
 
   /// Gets the [column] of the matrix
   Vector2 getColumn(int column) {
-    final r = new Vector2.zero();
-    final entry = column * 2;
-    final rStorage = r._v2storage;
+    final Vector2 r = new Vector2.zero();
+    final int entry = column * 2;
+    final Float32List rStorage = r._v2storage;
     rStorage[1] = _m2storage[entry + 1];
     rStorage[0] = _m2storage[entry + 0];
     return r;
@@ -206,7 +207,7 @@
 
   /// Copy [this] into [arg].
   Matrix2 copyInto(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float32List argStorage = arg._m2storage;
     argStorage[0] = _m2storage[0];
     argStorage[1] = _m2storage[1];
     argStorage[2] = _m2storage[2];
@@ -215,14 +216,14 @@
   }
 
   /// Returns a new vector or matrix by multiplying [this] with [arg].
-  operator *(dynamic arg) {
+  dynamic operator *(dynamic arg) {
     if (arg is double) {
       return scaled(arg);
     }
     if (arg is Vector2) {
       return transformed(arg);
     }
-    if (arg.dimension == 2) {
+    if (arg is Matrix2) {
       return multiplied(arg);
     }
     throw new ArgumentError(arg);
@@ -257,15 +258,15 @@
   Matrix2 transposed() => clone()..transpose();
 
   void transpose() {
-    double temp = _m2storage[2];
+    final double temp = _m2storage[2];
     _m2storage[2] = _m2storage[1];
     _m2storage[1] = temp;
   }
 
   /// Returns the component wise absolute value of this.
   Matrix2 absolute() {
-    Matrix2 r = new Matrix2.zero();
-    final rStorage = r._m2storage;
+    final Matrix2 r = new Matrix2.zero();
+    final Float32List rStorage = r._m2storage;
     rStorage[0] = _m2storage[0].abs();
     rStorage[1] = _m2storage[1].abs();
     rStorage[2] = _m2storage[2].abs();
@@ -279,13 +280,13 @@
 
   /// Returns the dot product of row [i] and [v].
   double dotRow(int i, Vector2 v) {
-    final vStorage = v._v2storage;
+    final Float32List vStorage = v._v2storage;
     return _m2storage[i] * vStorage[0] + _m2storage[2 + i] * vStorage[1];
   }
 
   /// Returns the dot product of column [j] and [v].
   double dotColumn(int j, Vector2 v) {
-    final vStorage = v._v2storage;
+    final Float32List vStorage = v._v2storage;
     return _m2storage[j * 2] * vStorage[0] +
         _m2storage[(j * 2) + 1] * vStorage[1];
   }
@@ -318,28 +319,28 @@
 
   /// Returns relative error between [this] and [correct]
   double relativeError(Matrix2 correct) {
-    Matrix2 diff = correct - this;
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = diff.infinityNorm();
+    final Matrix2 diff = correct - this;
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = diff.infinityNorm();
     return diff_norm / correct_norm;
   }
 
   /// Returns absolute error between [this] and [correct]
   double absoluteError(Matrix2 correct) {
-    double this_norm = infinityNorm();
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = (this_norm - correct_norm).abs();
+    final double this_norm = infinityNorm();
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = (this_norm - correct_norm).abs();
     return diff_norm;
   }
 
   /// Invert the matrix. Returns the determinant.
   double invert() {
-    double det = determinant();
+    final double det = determinant();
     if (det == 0.0) {
       return 0.0;
     }
-    double invDet = 1.0 / det;
-    double temp = _m2storage[0];
+    final double invDet = 1.0 / det;
+    final double temp = _m2storage[0];
     _m2storage[0] = _m2storage[3] * invDet;
     _m2storage[1] = -_m2storage[1] * invDet;
     _m2storage[2] = -_m2storage[2] * invDet;
@@ -349,13 +350,13 @@
 
   /// Set this matrix to be the inverse of [arg]
   double copyInverse(Matrix2 arg) {
-    double det = arg.determinant();
+    final double det = arg.determinant();
     if (det == 0.0) {
       setFrom(arg);
       return 0.0;
     }
-    double invDet = 1.0 / det;
-    final argStorage = arg._m2storage;
+    final double invDet = 1.0 / det;
+    final Float32List argStorage = arg._m2storage;
     _m2storage[0] = argStorage[3] * invDet;
     _m2storage[1] = -argStorage[1] * invDet;
     _m2storage[2] = -argStorage[2] * invDet;
@@ -365,8 +366,8 @@
 
   /// Turns the matrix into a rotation of [radians]
   void setRotation(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m2storage[0] = c;
     _m2storage[1] = s;
     _m2storage[2] = -s;
@@ -375,7 +376,7 @@
 
   /// Converts into Adjugate matrix and scales by [scale]
   void scaleAdjoint(double scale) {
-    double temp = _m2storage[0];
+    final double temp = _m2storage[0];
     _m2storage[0] = _m2storage[3] * scale;
     _m2storage[2] = -_m2storage[2] * scale;
     _m2storage[1] = -_m2storage[1] * scale;
@@ -395,7 +396,7 @@
 
   /// Add [o] to [this].
   void add(Matrix2 o) {
-    final oStorage = o._m2storage;
+    final Float32List oStorage = o._m2storage;
     _m2storage[0] = _m2storage[0] + oStorage[0];
     _m2storage[1] = _m2storage[1] + oStorage[1];
     _m2storage[2] = _m2storage[2] + oStorage[2];
@@ -404,7 +405,7 @@
 
   /// Subtract [o] from [this].
   void sub(Matrix2 o) {
-    final oStorage = o._m2storage;
+    final Float32List oStorage = o._m2storage;
     _m2storage[0] = _m2storage[0] - oStorage[0];
     _m2storage[1] = _m2storage[1] - oStorage[1];
     _m2storage[2] = _m2storage[2] - oStorage[2];
@@ -421,15 +422,15 @@
 
   /// Multiply [this] with [arg] and store it in [this].
   void multiply(Matrix2 arg) {
-    final m00 = _m2storage[0];
-    final m01 = _m2storage[2];
-    final m10 = _m2storage[1];
-    final m11 = _m2storage[3];
-    final argStorage = arg._m2storage;
-    final n00 = argStorage[0];
-    final n01 = argStorage[2];
-    final n10 = argStorage[1];
-    final n11 = argStorage[3];
+    final double m00 = _m2storage[0];
+    final double m01 = _m2storage[2];
+    final double m10 = _m2storage[1];
+    final double m11 = _m2storage[3];
+    final Float32List argStorage = arg._m2storage;
+    final double n00 = argStorage[0];
+    final double n01 = argStorage[2];
+    final double n10 = argStorage[1];
+    final double n11 = argStorage[3];
     _m2storage[0] = (m00 * n00) + (m01 * n10);
     _m2storage[2] = (m00 * n01) + (m01 * n11);
     _m2storage[1] = (m10 * n00) + (m11 * n10);
@@ -441,11 +442,11 @@
 
   /// Multiply a transposed [this] with [arg].
   void transposeMultiply(Matrix2 arg) {
-    final m00 = _m2storage[0];
-    final m01 = _m2storage[1];
-    final m10 = _m2storage[2];
-    final m11 = _m2storage[3];
-    final argStorage = arg._m2storage;
+    final double m00 = _m2storage[0];
+    final double m01 = _m2storage[1];
+    final double m10 = _m2storage[2];
+    final double m11 = _m2storage[3];
+    final Float32List argStorage = arg._m2storage;
     _m2storage[0] = (m00 * argStorage[0]) + (m01 * argStorage[1]);
     _m2storage[2] = (m00 * argStorage[2]) + (m01 * argStorage[3]);
     _m2storage[1] = (m10 * argStorage[0]) + (m11 * argStorage[1]);
@@ -454,11 +455,11 @@
 
   /// Multiply [this] with a transposed [arg].
   void multiplyTranspose(Matrix2 arg) {
-    final m00 = _m2storage[0];
-    final m01 = _m2storage[2];
-    final m10 = _m2storage[1];
-    final m11 = _m2storage[3];
-    final argStorage = arg._m2storage;
+    final double m00 = _m2storage[0];
+    final double m01 = _m2storage[2];
+    final double m10 = _m2storage[1];
+    final double m11 = _m2storage[3];
+    final Float32List argStorage = arg._m2storage;
     _m2storage[0] = (m00 * argStorage[0]) + (m01 * argStorage[2]);
     _m2storage[2] = (m00 * argStorage[1]) + (m01 * argStorage[3]);
     _m2storage[1] = (m10 * argStorage[0]) + (m11 * argStorage[2]);
@@ -468,9 +469,11 @@
   /// Transform [arg] of type [Vector2] using the transformation defined by
   /// [this].
   Vector2 transform(Vector2 arg) {
-    final argStorage = arg._v2storage;
-    final x = (_m2storage[0] * argStorage[0]) + (_m2storage[2] * argStorage[1]);
-    final y = (_m2storage[1] * argStorage[0]) + (_m2storage[3] * argStorage[1]);
+    final Float32List argStorage = arg._v2storage;
+    final double x =
+        (_m2storage[0] * argStorage[0]) + (_m2storage[2] * argStorage[1]);
+    final double y =
+        (_m2storage[1] * argStorage[0]) + (_m2storage[3] * argStorage[1]);
     argStorage[0] = x;
     argStorage[1] = y;
     return arg;
@@ -490,7 +493,7 @@
 
   /// Copies [this] into [array] starting at [offset].
   void copyIntoArray(List<num> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     array[i + 3] = _m2storage[3];
     array[i + 2] = _m2storage[2];
     array[i + 1] = _m2storage[1];
@@ -499,7 +502,7 @@
 
   /// Copies elements from [array] into [this] starting at [offset].
   void copyFromArray(List<double> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     _m2storage[3] = array[i + 3];
     _m2storage[2] = array[i + 2];
     _m2storage[1] = array[i + 1];
diff --git a/pub/vector_math/lib/src/vector_math/matrix3.dart b/pub/vector_math/lib/src/vector_math/matrix3.dart
index 6f65541..a8f0e49 100644
--- a/pub/vector_math/lib/src/vector_math/matrix3.dart
+++ b/pub/vector_math/lib/src/vector_math/matrix3.dart
@@ -26,8 +26,9 @@
       det = 1.0 / det;
     }
 
-    x.x = det * (a22 * bx - a12 * by);
-    x.y = det * (a11 * by - a21 * bx);
+    x
+      ..x = det * (a22 * bx - a12 * by)
+      ..y = det * (a11 * by - a21 * bx);
   }
 
   /// Solve [A] * [x] = [b].
@@ -72,9 +73,10 @@
     // Column0 dot -[b cross Column 1]
     final double z_ = det * (A0x * rx + A0y * ry + A0z * rz);
 
-    x.x = x_;
-    x.y = y_;
-    x.z = z_;
+    x
+      ..x = x_
+      ..y = y_
+      ..z = z_;
   }
 
   /// Return index in storage for [row], [col] value.
@@ -89,7 +91,7 @@
   }
 
   /// Set value at [row], [col] to be [v].
-  setEntry(int row, int col, double v) {
+  void setEntry(int row, int col, double v) {
     assert((row >= 0) && (row < dimension));
     assert((col >= 0) && (col < dimension));
 
@@ -103,11 +105,9 @@
         ..setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
 
   /// New matrix from [values].
-  factory Matrix3.fromList(List<double> values) {
-    return new Matrix3.zero()
-      ..setValues(values[0], values[1], values[2], values[3], values[4],
-          values[5], values[6], values[7], values[8]);
-  }
+  factory Matrix3.fromList(List<double> values) => new Matrix3.zero()
+    ..setValues(values[0], values[1], values[2], values[3], values[4],
+        values[5], values[6], values[7], values[8]);
 
   /// Constructs a new [Matrix3] filled with zeros.
   Matrix3.zero() : _m3storage = new Float32List(9);
@@ -154,9 +154,9 @@
 
   /// Sets the entire matrix to the column values.
   void setColumns(Vector3 arg0, Vector3 arg1, Vector3 arg2) {
-    final arg0Storage = arg0._v3storage;
-    final arg1Storage = arg1._v3storage;
-    final arg2Storage = arg2._v3storage;
+    final Float32List arg0Storage = arg0._v3storage;
+    final Float32List arg1Storage = arg1._v3storage;
+    final Float32List arg2Storage = arg2._v3storage;
     _m3storage[0] = arg0Storage[0];
     _m3storage[1] = arg0Storage[1];
     _m3storage[2] = arg0Storage[2];
@@ -170,7 +170,7 @@
 
   /// Sets the entire matrix to the matrix in [arg].
   void setFrom(Matrix3 arg) {
-    final argStorage = arg._m3storage;
+    final Float32List argStorage = arg._m3storage;
     _m3storage[8] = argStorage[8];
     _m3storage[7] = argStorage[7];
     _m3storage[6] = argStorage[6];
@@ -184,8 +184,8 @@
 
   /// Set [this] to the outer product of [u] and [v].
   void setOuter(Vector3 u, Vector3 v) {
-    final uStorage = u._v3storage;
-    final vStorage = v._v3storage;
+    final Float32List uStorage = u._v3storage;
+    final Float32List vStorage = v._v3storage;
     _m3storage[0] = uStorage[0] * vStorage[0];
     _m3storage[1] = uStorage[0] * vStorage[1];
     _m3storage[2] = uStorage[0] * vStorage[2];
@@ -213,7 +213,7 @@
 
   /// Sets the upper 2x2 of the matrix to be [arg].
   void setUpper2x2(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float32List argStorage = arg._m2storage;
     _m3storage[0] = argStorage[0];
     _m3storage[1] = argStorage[1];
     _m3storage[3] = argStorage[2];
@@ -221,6 +221,7 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n[2] ${getRow(2)}\n';
 
   /// Dimension of the matrix.
@@ -235,19 +236,20 @@
   }
 
   /// Check if two matrices are the same.
-  bool operator ==(other) {
-    return (other is Matrix3) &&
-        (_m3storage[0] == other._m3storage[0]) &&
-        (_m3storage[1] == other._m3storage[1]) &&
-        (_m3storage[2] == other._m3storage[2]) &&
-        (_m3storage[3] == other._m3storage[3]) &&
-        (_m3storage[4] == other._m3storage[4]) &&
-        (_m3storage[5] == other._m3storage[5]) &&
-        (_m3storage[6] == other._m3storage[6]) &&
-        (_m3storage[7] == other._m3storage[7]) &&
-        (_m3storage[8] == other._m3storage[8]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Matrix3) &&
+      (_m3storage[0] == other._m3storage[0]) &&
+      (_m3storage[1] == other._m3storage[1]) &&
+      (_m3storage[2] == other._m3storage[2]) &&
+      (_m3storage[3] == other._m3storage[3]) &&
+      (_m3storage[4] == other._m3storage[4]) &&
+      (_m3storage[5] == other._m3storage[5]) &&
+      (_m3storage[6] == other._m3storage[6]) &&
+      (_m3storage[7] == other._m3storage[7]) &&
+      (_m3storage[8] == other._m3storage[8]);
 
+  @override
   int get hashCode => quiver.hashObjects(_m3storage);
 
   /// Returns row 0
@@ -270,7 +272,7 @@
 
   /// Assigns the [row] of to [arg].
   void setRow(int row, Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _m3storage[index(row, 0)] = argStorage[0];
     _m3storage[index(row, 1)] = argStorage[1];
     _m3storage[index(row, 2)] = argStorage[2];
@@ -278,8 +280,8 @@
 
   /// Gets the [row] of the matrix
   Vector3 getRow(int row) {
-    Vector3 r = new Vector3.zero();
-    final rStorage = r._v3storage;
+    final Vector3 r = new Vector3.zero();
+    final Float32List rStorage = r._v3storage;
     rStorage[0] = _m3storage[index(row, 0)];
     rStorage[1] = _m3storage[index(row, 1)];
     rStorage[2] = _m3storage[index(row, 2)];
@@ -288,8 +290,8 @@
 
   /// Assigns the [column] of the matrix [arg]
   void setColumn(int column, Vector3 arg) {
-    final argStorage = arg._v3storage;
-    int entry = column * 3;
+    final Float32List argStorage = arg._v3storage;
+    final int entry = column * 3;
     _m3storage[entry + 2] = argStorage[2];
     _m3storage[entry + 1] = argStorage[1];
     _m3storage[entry + 0] = argStorage[0];
@@ -297,9 +299,9 @@
 
   /// Gets the [column] of the matrix
   Vector3 getColumn(int column) {
-    Vector3 r = new Vector3.zero();
-    final rStorage = r._v3storage;
-    int entry = column * 3;
+    final Vector3 r = new Vector3.zero();
+    final Float32List rStorage = r._v3storage;
+    final int entry = column * 3;
     rStorage[2] = _m3storage[entry + 2];
     rStorage[1] = _m3storage[entry + 1];
     rStorage[0] = _m3storage[entry + 0];
@@ -311,7 +313,7 @@
 
   /// Copy [this] into [arg].
   Matrix3 copyInto(Matrix3 arg) {
-    final argStorage = arg._m3storage;
+    final Float32List argStorage = arg._m3storage;
     argStorage[0] = _m3storage[0];
     argStorage[1] = _m3storage[1];
     argStorage[2] = _m3storage[2];
@@ -325,14 +327,14 @@
   }
 
   /// Returns a new vector or matrix by multiplying [this] with [arg].
-  operator *(dynamic arg) {
+  dynamic operator *(dynamic arg) {
     if (arg is double) {
       return scaled(arg);
     }
     if (arg is Vector3) {
       return transformed(arg);
     }
-    if (arg.dimension == 3) {
+    if (arg is Matrix3) {
       return multiplied(arg);
     }
     throw new ArgumentError(arg);
@@ -392,8 +394,8 @@
 
   /// Returns the component wise absolute value of this.
   Matrix3 absolute() {
-    Matrix3 r = new Matrix3.zero();
-    final rStorage = r._m3storage;
+    final Matrix3 r = new Matrix3.zero();
+    final Float32List rStorage = r._m3storage;
     rStorage[0] = _m3storage[0].abs();
     rStorage[1] = _m3storage[1].abs();
     rStorage[2] = _m3storage[2].abs();
@@ -408,18 +410,18 @@
 
   /// Returns the determinant of this matrix.
   double determinant() {
-    double x = _m3storage[0] *
+    final double x = _m3storage[0] *
         ((storage[4] * _m3storage[8]) - (storage[5] * _m3storage[7]));
-    double y = _m3storage[1] *
+    final double y = _m3storage[1] *
         ((storage[3] * _m3storage[8]) - (storage[5] * _m3storage[6]));
-    double z = _m3storage[2] *
+    final double z = _m3storage[2] *
         ((storage[3] * _m3storage[7]) - (storage[4] * _m3storage[6]));
     return x - y + z;
   }
 
   /// Returns the dot product of row [i] and [v].
   double dotRow(int i, Vector3 v) {
-    final vStorage = v._v3storage;
+    final Float32List vStorage = v._v3storage;
     return _m3storage[i] * vStorage[0] +
         _m3storage[3 + i] * vStorage[1] +
         _m3storage[6 + i] * vStorage[2];
@@ -427,7 +429,7 @@
 
   /// Returns the dot product of column [j] and [v].
   double dotColumn(int j, Vector3 v) {
-    final vStorage = v._v3storage;
+    final Float32List vStorage = v._v3storage;
     return _m3storage[j * 3] * vStorage[0] +
         _m3storage[j * 3 + 1] * vStorage[1] +
         _m3storage[j * 3 + 2] * vStorage[2];
@@ -472,17 +474,17 @@
 
   /// Returns relative error between [this] and [correct]
   double relativeError(Matrix3 correct) {
-    Matrix3 diff = correct - this;
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = diff.infinityNorm();
+    final Matrix3 diff = correct - this;
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = diff.infinityNorm();
     return diff_norm / correct_norm;
   }
 
   /// Returns absolute error between [this] and [correct]
   double absoluteError(Matrix3 correct) {
-    double this_norm = infinityNorm();
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = (this_norm - correct_norm).abs();
+    final double this_norm = infinityNorm();
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = (this_norm - correct_norm).abs();
     return diff_norm;
   }
 
@@ -491,30 +493,30 @@
 
   /// Set this matrix to be the inverse of [arg]
   double copyInverse(Matrix3 arg) {
-    final det = arg.determinant();
+    final double det = arg.determinant();
     if (det == 0.0) {
       setFrom(arg);
       return 0.0;
     }
-    final invDet = 1.0 / det;
-    final argStorage = arg._m3storage;
-    final ix = invDet *
+    final double invDet = 1.0 / det;
+    final Float32List argStorage = arg._m3storage;
+    final double ix = invDet *
         (argStorage[4] * argStorage[8] - argStorage[5] * argStorage[7]);
-    final iy = invDet *
+    final double iy = invDet *
         (argStorage[2] * argStorage[7] - argStorage[1] * argStorage[8]);
-    final iz = invDet *
+    final double iz = invDet *
         (argStorage[1] * argStorage[5] - argStorage[2] * argStorage[4]);
-    final jx = invDet *
+    final double jx = invDet *
         (argStorage[5] * argStorage[6] - argStorage[3] * argStorage[8]);
-    final jy = invDet *
+    final double jy = invDet *
         (argStorage[0] * argStorage[8] - argStorage[2] * argStorage[6]);
-    final jz = invDet *
+    final double jz = invDet *
         (argStorage[2] * argStorage[3] - argStorage[0] * argStorage[5]);
-    final kx = invDet *
+    final double kx = invDet *
         (argStorage[3] * argStorage[7] - argStorage[4] * argStorage[6]);
-    final ky = invDet *
+    final double ky = invDet *
         (argStorage[1] * argStorage[6] - argStorage[0] * argStorage[7]);
-    final kz = invDet *
+    final double kz = invDet *
         (argStorage[0] * argStorage[4] - argStorage[1] * argStorage[3]);
     _m3storage[0] = ix;
     _m3storage[1] = iy;
@@ -536,8 +538,8 @@
 
   /// Turns the matrix into a rotation of [radians] around X
   void setRotationX(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m3storage[0] = 1.0;
     _m3storage[1] = 0.0;
     _m3storage[2] = 0.0;
@@ -551,8 +553,8 @@
 
   /// Turns the matrix into a rotation of [radians] around Y
   void setRotationY(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m3storage[0] = c;
     _m3storage[1] = 0.0;
     _m3storage[2] = s;
@@ -566,8 +568,8 @@
 
   /// Turns the matrix into a rotation of [radians] around Z
   void setRotationZ(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m3storage[0] = c;
     _m3storage[1] = s;
     _m3storage[2] = 0.0;
@@ -581,15 +583,15 @@
 
   /// Converts into Adjugate matrix and scales by [scale]
   void scaleAdjoint(double scale) {
-    double m00 = _m3storage[0];
-    double m01 = _m3storage[3];
-    double m02 = _m3storage[6];
-    double m10 = _m3storage[1];
-    double m11 = _m3storage[4];
-    double m12 = _m3storage[7];
-    double m20 = _m3storage[2];
-    double m21 = _m3storage[5];
-    double m22 = _m3storage[8];
+    final double m00 = _m3storage[0];
+    final double m01 = _m3storage[3];
+    final double m02 = _m3storage[6];
+    final double m10 = _m3storage[1];
+    final double m11 = _m3storage[4];
+    final double m12 = _m3storage[7];
+    final double m20 = _m3storage[2];
+    final double m21 = _m3storage[5];
+    final double m22 = _m3storage[8];
     _m3storage[0] = (m11 * m22 - m12 * m21) * scale;
     _m3storage[1] = (m12 * m20 - m10 * m22) * scale;
     _m3storage[2] = (m10 * m21 - m11 * m20) * scale;
@@ -605,19 +607,19 @@
   /// Returns [arg].
   /// Primarily used by AABB transformation code.
   Vector3 absoluteRotate(Vector3 arg) {
-    double m00 = _m3storage[0].abs();
-    double m01 = _m3storage[3].abs();
-    double m02 = _m3storage[6].abs();
-    double m10 = _m3storage[1].abs();
-    double m11 = _m3storage[4].abs();
-    double m12 = _m3storage[7].abs();
-    double m20 = _m3storage[2].abs();
-    double m21 = _m3storage[5].abs();
-    double m22 = _m3storage[8].abs();
-    final argStorage = arg._v3storage;
-    final x = argStorage[0];
-    final y = argStorage[1];
-    final z = argStorage[2];
+    final double m00 = _m3storage[0].abs();
+    final double m01 = _m3storage[3].abs();
+    final double m02 = _m3storage[6].abs();
+    final double m10 = _m3storage[1].abs();
+    final double m11 = _m3storage[4].abs();
+    final double m12 = _m3storage[7].abs();
+    final double m20 = _m3storage[2].abs();
+    final double m21 = _m3storage[5].abs();
+    final double m22 = _m3storage[8].abs();
+    final Float32List argStorage = arg._v3storage;
+    final double x = argStorage[0];
+    final double y = argStorage[1];
+    final double z = argStorage[2];
     argStorage[0] = x * m00 + y * m01 + z * m02;
     argStorage[1] = x * m10 + y * m11 + z * m12;
     argStorage[2] = x * m20 + y * m21 + z * m22;
@@ -628,13 +630,13 @@
   /// Returns [arg].
   /// Primarily used by AABB transformation code.
   Vector2 absoluteRotate2(Vector2 arg) {
-    double m00 = _m3storage[0].abs();
-    double m01 = _m3storage[3].abs();
-    double m10 = _m3storage[1].abs();
-    double m11 = _m3storage[4].abs();
-    final argStorage = arg._v2storage;
-    final x = argStorage[0];
-    final y = argStorage[1];
+    final double m00 = _m3storage[0].abs();
+    final double m01 = _m3storage[3].abs();
+    final double m10 = _m3storage[1].abs();
+    final double m11 = _m3storage[4].abs();
+    final Float32List argStorage = arg._v2storage;
+    final double x = argStorage[0];
+    final double y = argStorage[1];
     argStorage[0] = x * m00 + y * m01;
     argStorage[1] = x * m10 + y * m11;
     return arg;
@@ -642,11 +644,11 @@
 
   /// Transforms [arg] with [this].
   Vector2 transform2(Vector2 arg) {
-    final argStorage = arg._v2storage;
-    double x_ = (storage[0] * arg.storage[0]) +
+    final Float32List argStorage = arg._v2storage;
+    final double x_ = (storage[0] * arg.storage[0]) +
         (storage[3] * arg.storage[1]) +
         _m3storage[6];
-    double y_ = (storage[1] * arg.storage[0]) +
+    final double y_ = (storage[1] * arg.storage[0]) +
         (storage[4] * arg.storage[1]) +
         _m3storage[7];
     argStorage[0] = x_;
@@ -672,7 +674,7 @@
 
   /// Add [o] to [this].
   void add(Matrix3 o) {
-    final oStorage = o._m3storage;
+    final Float32List oStorage = o._m3storage;
     _m3storage[0] = _m3storage[0] + oStorage[0];
     _m3storage[1] = _m3storage[1] + oStorage[1];
     _m3storage[2] = _m3storage[2] + oStorage[2];
@@ -686,7 +688,7 @@
 
   /// Subtract [o] from [this].
   void sub(Matrix3 o) {
-    final oStorage = o._m3storage;
+    final Float32List oStorage = o._m3storage;
     _m3storage[0] = _m3storage[0] - oStorage[0];
     _m3storage[1] = _m3storage[1] - oStorage[1];
     _m3storage[2] = _m3storage[2] - oStorage[2];
@@ -722,7 +724,7 @@
     final double m20 = _m3storage[2];
     final double m21 = _m3storage[5];
     final double m22 = _m3storage[8];
-    final argStorage = arg._m3storage;
+    final Float32List argStorage = arg._m3storage;
     final double n00 = argStorage[0];
     final double n01 = argStorage[3];
     final double n02 = argStorage[6];
@@ -747,16 +749,16 @@
   Matrix3 multiplied(Matrix3 arg) => clone()..multiply(arg);
 
   void transposeMultiply(Matrix3 arg) {
-    double m00 = _m3storage[0];
-    double m01 = _m3storage[1];
-    double m02 = _m3storage[2];
-    double m10 = _m3storage[3];
-    double m11 = _m3storage[4];
-    double m12 = _m3storage[5];
-    double m20 = _m3storage[6];
-    double m21 = _m3storage[7];
-    double m22 = _m3storage[8];
-    final argStorage = arg._m3storage;
+    final double m00 = _m3storage[0];
+    final double m01 = _m3storage[1];
+    final double m02 = _m3storage[2];
+    final double m10 = _m3storage[3];
+    final double m11 = _m3storage[4];
+    final double m12 = _m3storage[5];
+    final double m20 = _m3storage[6];
+    final double m21 = _m3storage[7];
+    final double m22 = _m3storage[8];
+    final Float32List argStorage = arg._m3storage;
     _m3storage[0] =
         (m00 * argStorage[0]) + (m01 * arg.storage[1]) + (m02 * arg.storage[2]);
     _m3storage[3] =
@@ -778,16 +780,16 @@
   }
 
   void multiplyTranspose(Matrix3 arg) {
-    double m00 = _m3storage[0];
-    double m01 = _m3storage[3];
-    double m02 = _m3storage[6];
-    double m10 = _m3storage[1];
-    double m11 = _m3storage[4];
-    double m12 = _m3storage[7];
-    double m20 = _m3storage[2];
-    double m21 = _m3storage[5];
-    double m22 = _m3storage[8];
-    final argStorage = arg._m3storage;
+    final double m00 = _m3storage[0];
+    final double m01 = _m3storage[3];
+    final double m02 = _m3storage[6];
+    final double m10 = _m3storage[1];
+    final double m11 = _m3storage[4];
+    final double m12 = _m3storage[7];
+    final double m20 = _m3storage[2];
+    final double m21 = _m3storage[5];
+    final double m22 = _m3storage[8];
+    final Float32List argStorage = arg._m3storage;
     _m3storage[0] =
         (m00 * argStorage[0]) + (m01 * argStorage[3]) + (m02 * argStorage[6]);
     _m3storage[3] =
@@ -811,19 +813,20 @@
   /// Transform [arg] of type [Vector3] using the transformation defined by
   /// [this].
   Vector3 transform(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    double x_ = (storage[0] * argStorage[0]) +
+    final Float32List argStorage = arg._v3storage;
+    final double x_ = (storage[0] * argStorage[0]) +
         (storage[3] * argStorage[1]) +
         (storage[6] * argStorage[2]);
-    double y_ = (storage[1] * argStorage[0]) +
+    final double y_ = (storage[1] * argStorage[0]) +
         (storage[4] * argStorage[1]) +
         (storage[7] * argStorage[2]);
-    double z_ = (storage[2] * argStorage[0]) +
+    final double z_ = (storage[2] * argStorage[0]) +
         (storage[5] * argStorage[1]) +
         (storage[8] * argStorage[2]);
-    arg.x = x_;
-    arg.y = y_;
-    arg.z = z_;
+    arg
+      ..x = x_
+      ..y = y_
+      ..z = z_;
     return arg;
   }
 
@@ -841,7 +844,7 @@
 
   /// Copies [this] into [array] starting at [offset].
   void copyIntoArray(List<num> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     array[i + 8] = _m3storage[8];
     array[i + 7] = _m3storage[7];
     array[i + 6] = _m3storage[6];
@@ -855,7 +858,7 @@
 
   /// Copies elements from [array] into [this] starting at [offset].
   void copyFromArray(List<double> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     _m3storage[8] = array[i + 8];
     _m3storage[7] = array[i + 7];
     _m3storage[6] = array[i + 6];
@@ -869,8 +872,8 @@
 
   /// Multiply [this] to each set of xyz values in [array] starting at [offset].
   List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
-    for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
-      final v = new Vector3.array(array, j)..applyMatrix3(this);
+    for (int i = 0, j = offset; i < array.length; i += 3, j += 3) {
+      final Vector3 v = new Vector3.array(array, j)..applyMatrix3(this);
       array[j] = v.storage[0];
       array[j + 1] = v.storage[1];
       array[j + 2] = v.storage[2];
@@ -880,49 +883,53 @@
   }
 
   Vector3 get right {
-    double x = _m3storage[0];
-    double y = _m3storage[1];
-    double z = _m3storage[2];
+    final double x = _m3storage[0];
+    final double y = _m3storage[1];
+    final double z = _m3storage[2];
     return new Vector3(x, y, z);
   }
 
   Vector3 get up {
-    double x = _m3storage[3];
-    double y = _m3storage[4];
-    double z = _m3storage[5];
+    final double x = _m3storage[3];
+    final double y = _m3storage[4];
+    final double z = _m3storage[5];
     return new Vector3(x, y, z);
   }
 
   Vector3 get forward {
-    double x = _m3storage[6];
-    double y = _m3storage[7];
-    double z = _m3storage[8];
+    final double x = _m3storage[6];
+    final double y = _m3storage[7];
+    final double z = _m3storage[8];
     return new Vector3(x, y, z);
   }
 
   /// Is [this] the identity matrix?
-  bool isIdentity() {
-    return _m3storage[0] == 1.0 // col 1
-        && _m3storage[1] == 0.0
-        && _m3storage[2] == 0.0
-        && _m3storage[3] == 0.0 // col 2
-        && _m3storage[4] == 1.0
-        && _m3storage[5] == 0.0
-        && _m3storage[6] == 0.0 // col 3
-        && _m3storage[7] == 0.0
-        && _m3storage[8] == 1.0;
-  }
+  bool isIdentity() =>
+      _m3storage[0] == 1.0 // col 1
+      &&
+      _m3storage[1] == 0.0 &&
+      _m3storage[2] == 0.0 &&
+      _m3storage[3] == 0.0 // col 2
+      &&
+      _m3storage[4] == 1.0 &&
+      _m3storage[5] == 0.0 &&
+      _m3storage[6] == 0.0 // col 3
+      &&
+      _m3storage[7] == 0.0 &&
+      _m3storage[8] == 1.0;
 
   /// Is [this] the zero matrix?
-  bool isZero() {
-    return _m3storage[0] == 0.0 // col 1
-        && _m3storage[1] == 0.0
-        && _m3storage[2] == 0.0
-        && _m3storage[3] == 0.0 // col 2
-        && _m3storage[4] == 0.0
-        && _m3storage[5] == 0.0
-        && _m3storage[6] == 0.0 // col 3
-        && _m3storage[7] == 0.0
-        && _m3storage[8] == 0.0;
-  }
+  bool isZero() =>
+      _m3storage[0] == 0.0 // col 1
+      &&
+      _m3storage[1] == 0.0 &&
+      _m3storage[2] == 0.0 &&
+      _m3storage[3] == 0.0 // col 2
+      &&
+      _m3storage[4] == 0.0 &&
+      _m3storage[5] == 0.0 &&
+      _m3storage[6] == 0.0 // col 3
+      &&
+      _m3storage[7] == 0.0 &&
+      _m3storage[8] == 0.0;
 }
diff --git a/pub/vector_math/lib/src/vector_math/matrix4.dart b/pub/vector_math/lib/src/vector_math/matrix4.dart
index 0e3e4b4..94237e8 100644
--- a/pub/vector_math/lib/src/vector_math/matrix4.dart
+++ b/pub/vector_math/lib/src/vector_math/matrix4.dart
@@ -26,8 +26,9 @@
       det = 1.0 / det;
     }
 
-    x.x = det * (a22 * bx - a12 * by);
-    x.y = det * (a11 * by - a21 * bx);
+    x
+      ..x = det * (a22 * bx - a12 * by)
+      ..y = det * (a11 * by - a21 * bx);
   }
 
   /// Solve [A] * [x] = [b].
@@ -75,9 +76,10 @@
     // Column0 dot -[b cross Column 1]
     final double z_ = det * (A0x * rx + A0y * ry + A0z * rz);
 
-    x.x = x_;
-    x.y = y_;
-    x.z = z_;
+    x
+      ..x = x_
+      ..y = y_
+      ..z = z_;
   }
 
   /// Solve [A] * [x] = [b].
@@ -123,29 +125,27 @@
       det = 1.0 / det;
     }
 
-    x.x = det *
-        ((a11 * b11 - a12 * b10 + a13 * b09) * bX -
-            (a10 * b11 - a12 * b08 + a13 * b07) * bY +
-            (a10 * b10 - a11 * b08 + a13 * b06) * bZ -
-            (a10 * b09 - a11 * b07 + a12 * b06) * bW);
-
-    x.y = det *
-        -((a01 * b11 - a02 * b10 + a03 * b09) * bX -
-            (a00 * b11 - a02 * b08 + a03 * b07) * bY +
-            (a00 * b10 - a01 * b08 + a03 * b06) * bZ -
-            (a00 * b09 - a01 * b07 + a02 * b06) * bW);
-
-    x.z = det *
-        ((a31 * b05 - a32 * b04 + a33 * b03) * bX -
-            (a30 * b05 - a32 * b02 + a33 * b01) * bY +
-            (a30 * b04 - a31 * b02 + a33 * b00) * bZ -
-            (a30 * b03 - a31 * b01 + a32 * b00) * bW);
-
-    x.w = det *
-        -((a21 * b05 - a22 * b04 + a23 * b03) * bX -
-            (a20 * b05 - a22 * b02 + a23 * b01) * bY +
-            (a20 * b04 - a21 * b02 + a23 * b00) * bZ -
-            (a20 * b03 - a21 * b01 + a22 * b00) * bW);
+    x
+      ..x = det *
+          ((a11 * b11 - a12 * b10 + a13 * b09) * bX -
+              (a10 * b11 - a12 * b08 + a13 * b07) * bY +
+              (a10 * b10 - a11 * b08 + a13 * b06) * bZ -
+              (a10 * b09 - a11 * b07 + a12 * b06) * bW)
+      ..y = det *
+          -((a01 * b11 - a02 * b10 + a03 * b09) * bX -
+              (a00 * b11 - a02 * b08 + a03 * b07) * bY +
+              (a00 * b10 - a01 * b08 + a03 * b06) * bZ -
+              (a00 * b09 - a01 * b07 + a02 * b06) * bW)
+      ..z = det *
+          ((a31 * b05 - a32 * b04 + a33 * b03) * bX -
+              (a30 * b05 - a32 * b02 + a33 * b01) * bY +
+              (a30 * b04 - a31 * b02 + a33 * b00) * bZ -
+              (a30 * b03 - a31 * b01 + a32 * b00) * bW)
+      ..w = det *
+          -((a21 * b05 - a22 * b04 + a23 * b03) * bX -
+              (a20 * b05 - a22 * b02 + a23 * b01) * bY +
+              (a20 * b04 - a21 * b02 + a23 * b00) * bZ -
+              (a20 * b03 - a21 * b01 + a22 * b00) * bW);
   }
 
   /// Return index in storage for [row], [col] value.
@@ -160,7 +160,7 @@
   }
 
   /// Set value at [row], [col] to be [v].
-  setEntry(int row, int col, double v) {
+  void setEntry(int row, int col, double v) {
     assert((row >= 0) && (row < dimension));
     assert((col >= 0) && (col < dimension));
 
@@ -190,26 +190,24 @@
             arg10, arg11, arg12, arg13, arg14, arg15);
 
   /// New matrix from [values].
-  factory Matrix4.fromList(List<double> values) {
-    return new Matrix4.zero()
-      ..setValues(
-          values[0],
-          values[1],
-          values[2],
-          values[3],
-          values[4],
-          values[5],
-          values[6],
-          values[7],
-          values[8],
-          values[9],
-          values[10],
-          values[11],
-          values[12],
-          values[13],
-          values[14],
-          values[15]);
-  }
+  factory Matrix4.fromList(List<double> values) => new Matrix4.zero()
+    ..setValues(
+        values[0],
+        values[1],
+        values[2],
+        values[3],
+        values[4],
+        values[5],
+        values[6],
+        values[7],
+        values[8],
+        values[9],
+        values[10],
+        values[11],
+        values[12],
+        values[13],
+        values[14],
+        values[15]);
 
   /// Zero matrix.
   Matrix4.zero() : _m4storage = new Float32List(16);
@@ -222,8 +220,8 @@
 
   /// Constructs a matrix that is the inverse of [other].
   factory Matrix4.inverted(Matrix4 other) {
-    Matrix4 r = new Matrix4.zero();
-    double determinant = r.copyInverse(other);
+    final Matrix4 r = new Matrix4.zero();
+    final double determinant = r.copyInverse(other);
     if (determinant == 0.0) {
       throw new ArgumentError.value(
           other, 'other', 'Matrix cannot be inverted');
@@ -268,9 +266,9 @@
 
   /// Scale matrix.
   factory Matrix4.diagonal3(Vector3 scale) {
-    final m = new Matrix4.zero();
-    final mStorage = m._m4storage;
-    final scaleStorage = scale._v3storage;
+    final Matrix4 m = new Matrix4.zero();
+    final Float32List mStorage = m._m4storage;
+    final Float32List scaleStorage = scale._v3storage;
     mStorage[15] = 1.0;
     mStorage[10] = scaleStorage[2];
     mStorage[5] = scaleStorage[1];
@@ -288,27 +286,26 @@
 
   /// Skew matrix around X axis
   factory Matrix4.skewX(double alpha) {
-    final m = new Matrix4.identity();
-    m._m4storage[4] = Math.tan(alpha);
+    final Matrix4 m = new Matrix4.identity();
+    m._m4storage[4] = math.tan(alpha);
     return m;
   }
 
   /// Skew matrix around Y axis.
   factory Matrix4.skewY(double beta) {
-    final m = new Matrix4.identity();
-    m._m4storage[1] = Math.tan(beta);
+    final Matrix4 m = new Matrix4.identity();
+    m._m4storage[1] = math.tan(beta);
     return m;
   }
 
   /// Skew matrix around X axis (alpha) and Y axis (beta).
   factory Matrix4.skew(double alpha, double beta) {
-    final m = new Matrix4.identity();
-    m._m4storage[1] = Math.tan(beta);
-    m._m4storage[4] = Math.tan(alpha);
+    final Matrix4 m = new Matrix4.identity();
+    m._m4storage[1] = math.tan(beta);
+    m._m4storage[4] = math.tan(alpha);
     return m;
   }
 
-
   /// Constructs Matrix4 with given [Float32List] as [storage].
   Matrix4.fromFloat32List(this._m4storage);
 
@@ -369,10 +366,10 @@
 
   /// Sets the entire matrix to the column values.
   void setColumns(Vector4 arg0, Vector4 arg1, Vector4 arg2, Vector4 arg3) {
-    final arg0Storage = arg0._v4storage;
-    final arg1Storage = arg1._v4storage;
-    final arg2Storage = arg2._v4storage;
-    final arg3Storage = arg3._v4storage;
+    final Float32List arg0Storage = arg0._v4storage;
+    final Float32List arg1Storage = arg1._v4storage;
+    final Float32List arg2Storage = arg2._v4storage;
+    final Float32List arg3Storage = arg3._v4storage;
     _m4storage[0] = arg0Storage[0];
     _m4storage[1] = arg0Storage[1];
     _m4storage[2] = arg0Storage[2];
@@ -393,7 +390,7 @@
 
   /// Sets the entire matrix to the matrix in [arg].
   void setFrom(Matrix4 arg) {
-    final argStorage = arg._m4storage;
+    final Float32List argStorage = arg._m4storage;
     _m4storage[15] = argStorage[15];
     _m4storage[14] = argStorage[14];
     _m4storage[13] = argStorage[13];
@@ -414,25 +411,25 @@
 
   /// Sets the matrix from translation [arg0] and rotation [arg1].
   void setFromTranslationRotation(Vector3 arg0, Quaternion arg1) {
-    final arg1Storage = arg1._qStorage;
-    double x = arg1Storage[0];
-    double y = arg1Storage[1];
-    double z = arg1Storage[2];
-    double w = arg1Storage[3];
-    double x2 = x + x;
-    double y2 = y + y;
-    double z2 = z + z;
-    double xx = x * x2;
-    double xy = x * y2;
-    double xz = x * z2;
-    double yy = y * y2;
-    double yz = y * z2;
-    double zz = z * z2;
-    double wx = w * x2;
-    double wy = w * y2;
-    double wz = w * z2;
+    final Float32List arg1Storage = arg1._qStorage;
+    final double x = arg1Storage[0];
+    final double y = arg1Storage[1];
+    final double z = arg1Storage[2];
+    final double w = arg1Storage[3];
+    final double x2 = x + x;
+    final double y2 = y + y;
+    final double z2 = z + z;
+    final double xx = x * x2;
+    final double xy = x * y2;
+    final double xz = x * z2;
+    final double yy = y * y2;
+    final double yz = y * z2;
+    final double zz = z * z2;
+    final double wx = w * x2;
+    final double wy = w * y2;
+    final double wz = w * z2;
 
-    final arg0Storage = arg0._v3storage;
+    final Float32List arg0Storage = arg0._v3storage;
     _m4storage[0] = 1.0 - (yy + zz);
     _m4storage[1] = xy + wz;
     _m4storage[2] = xz - wy;
@@ -460,7 +457,7 @@
 
   /// Sets the upper 2x2 of the matrix to be [arg].
   void setUpper2x2(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float32List argStorage = arg._m2storage;
     _m4storage[0] = argStorage[0];
     _m4storage[1] = argStorage[1];
     _m4storage[4] = argStorage[2];
@@ -469,7 +466,7 @@
 
   /// Sets the diagonal of the matrix to be [arg].
   void setDiagonal(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _m4storage[0] = argStorage[0];
     _m4storage[5] = argStorage[1];
     _m4storage[10] = argStorage[2];
@@ -477,8 +474,8 @@
   }
 
   void setOuter(Vector4 u, Vector4 v) {
-    final uStorage = u._v4storage;
-    final vStorage = v._v4storage;
+    final Float32List uStorage = u._v4storage;
+    final Float32List vStorage = v._v4storage;
     _m4storage[0] = uStorage[0] * vStorage[0];
     _m4storage[1] = uStorage[0] * vStorage[1];
     _m4storage[2] = uStorage[0] * vStorage[2];
@@ -498,6 +495,7 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n'
       '[2] ${getRow(2)}\n[3] ${getRow(3)}\n';
 
@@ -513,26 +511,27 @@
   }
 
   /// Check if two matrices are the same.
-  bool operator ==(other) {
-    return (other is Matrix4) &&
-        (_m4storage[0] == other._m4storage[0]) &&
-        (_m4storage[1] == other._m4storage[1]) &&
-        (_m4storage[2] == other._m4storage[2]) &&
-        (_m4storage[3] == other._m4storage[3]) &&
-        (_m4storage[4] == other._m4storage[4]) &&
-        (_m4storage[5] == other._m4storage[5]) &&
-        (_m4storage[6] == other._m4storage[6]) &&
-        (_m4storage[7] == other._m4storage[7]) &&
-        (_m4storage[8] == other._m4storage[8]) &&
-        (_m4storage[9] == other._m4storage[9]) &&
-        (_m4storage[10] == other._m4storage[10]) &&
-        (_m4storage[11] == other._m4storage[11]) &&
-        (_m4storage[12] == other._m4storage[12]) &&
-        (_m4storage[13] == other._m4storage[13]) &&
-        (_m4storage[14] == other._m4storage[14]) &&
-        (_m4storage[15] == other._m4storage[15]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Matrix4) &&
+      (_m4storage[0] == other._m4storage[0]) &&
+      (_m4storage[1] == other._m4storage[1]) &&
+      (_m4storage[2] == other._m4storage[2]) &&
+      (_m4storage[3] == other._m4storage[3]) &&
+      (_m4storage[4] == other._m4storage[4]) &&
+      (_m4storage[5] == other._m4storage[5]) &&
+      (_m4storage[6] == other._m4storage[6]) &&
+      (_m4storage[7] == other._m4storage[7]) &&
+      (_m4storage[8] == other._m4storage[8]) &&
+      (_m4storage[9] == other._m4storage[9]) &&
+      (_m4storage[10] == other._m4storage[10]) &&
+      (_m4storage[11] == other._m4storage[11]) &&
+      (_m4storage[12] == other._m4storage[12]) &&
+      (_m4storage[13] == other._m4storage[13]) &&
+      (_m4storage[14] == other._m4storage[14]) &&
+      (_m4storage[15] == other._m4storage[15]);
 
+  @override
   int get hashCode => quiver.hashObjects(_m4storage);
 
   /// Returns row 0
@@ -561,7 +560,7 @@
 
   /// Assigns the [row] of the matrix [arg]
   void setRow(int row, Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _m4storage[index(row, 0)] = argStorage[0];
     _m4storage[index(row, 1)] = argStorage[1];
     _m4storage[index(row, 2)] = argStorage[2];
@@ -570,8 +569,8 @@
 
   /// Gets the [row] of the matrix
   Vector4 getRow(int row) {
-    Vector4 r = new Vector4.zero();
-    final rStorage = r._v4storage;
+    final Vector4 r = new Vector4.zero();
+    final Float32List rStorage = r._v4storage;
     rStorage[0] = _m4storage[index(row, 0)];
     rStorage[1] = _m4storage[index(row, 1)];
     rStorage[2] = _m4storage[index(row, 2)];
@@ -581,8 +580,8 @@
 
   /// Assigns the [column] of the matrix [arg]
   void setColumn(int column, Vector4 arg) {
-    int entry = column * 4;
-    final argStorage = arg._v4storage;
+    final int entry = column * 4;
+    final Float32List argStorage = arg._v4storage;
     _m4storage[entry + 3] = argStorage[3];
     _m4storage[entry + 2] = argStorage[2];
     _m4storage[entry + 1] = argStorage[1];
@@ -591,9 +590,9 @@
 
   /// Gets the [column] of the matrix
   Vector4 getColumn(int column) {
-    Vector4 r = new Vector4.zero();
-    final rStorage = r._v4storage;
-    int entry = column * 4;
+    final Vector4 r = new Vector4.zero();
+    final Float32List rStorage = r._v4storage;
+    final int entry = column * 4;
     rStorage[3] = _m4storage[entry + 3];
     rStorage[2] = _m4storage[entry + 2];
     rStorage[1] = _m4storage[entry + 1];
@@ -606,7 +605,7 @@
 
   /// Copy into [arg].
   Matrix4 copyInto(Matrix4 arg) {
-    final argStorage = arg._m4storage;
+    final Float32List argStorage = arg._m4storage;
     argStorage[0] = _m4storage[0];
     argStorage[1] = _m4storage[1];
     argStorage[2] = _m4storage[2];
@@ -640,7 +639,7 @@
     if (arg is Vector3) {
       return transformed3(arg);
     }
-    if (arg.dimension == 4) {
+    if (arg is Matrix4) {
       return multiplied(arg);
     }
     throw new ArgumentError(arg);
@@ -653,33 +652,37 @@
   Matrix4 operator -(Matrix4 arg) => clone()..sub(arg);
 
   /// Translate this matrix by a [Vector3], [Vector4], or x,y,z
-  void translate(x, [double y = 0.0, double z = 0.0]) {
+  void translate(dynamic x, [double y = 0.0, double z = 0.0]) {
     double tx;
     double ty;
     double tz;
-    double tw = x is Vector4 ? x.w : 1.0;
-    if (x is Vector3 || x is Vector4) {
+    final double tw = x is Vector4 ? x.w : 1.0;
+    if (x is Vector3) {
       tx = x.x;
       ty = x.y;
       tz = x.z;
-    } else {
+    } else if (x is Vector4) {
+      tx = x.x;
+      ty = x.y;
+      tz = x.z;
+    } else if (x is double) {
       tx = x;
       ty = y;
       tz = z;
     }
-    var t1 = _m4storage[0] * tx +
+    final double t1 = _m4storage[0] * tx +
         _m4storage[4] * ty +
         _m4storage[8] * tz +
         _m4storage[12] * tw;
-    var t2 = _m4storage[1] * tx +
+    final double t2 = _m4storage[1] * tx +
         _m4storage[5] * ty +
         _m4storage[9] * tz +
         _m4storage[13] * tw;
-    var t3 = _m4storage[2] * tx +
+    final double t3 = _m4storage[2] * tx +
         _m4storage[6] * ty +
         _m4storage[10] * tz +
         _m4storage[14] * tw;
-    var t4 = _m4storage[3] * tx +
+    final double t4 = _m4storage[3] * tx +
         _m4storage[7] * ty +
         _m4storage[11] * tz +
         _m4storage[15] * tw;
@@ -691,16 +694,20 @@
 
   /// Multiply [this] by a translation from the left.
   /// The translation can be specified with a  [Vector3], [Vector4], or x, y, z.
-  void leftTranslate(x, [double y = 0.0, double z = 0.0]) {
+  void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) {
     double tx;
     double ty;
     double tz;
-    double tw = x is Vector4 ? x.w : 1.0;
-    if (x is Vector3 || x is Vector4) {
+    final double tw = x is Vector4 ? x.w : 1.0;
+    if (x is Vector3) {
       tx = x.x;
       ty = x.y;
       tz = x.z;
-    } else {
+    } else if (x is Vector4) {
+      tx = x.x;
+      ty = x.y;
+      tz = x.z;
+    } else if (x is double) {
       tx = x;
       ty = y;
       tz = z;
@@ -733,35 +740,47 @@
 
   /// Rotate this [angle] radians around [axis]
   void rotate(Vector3 axis, double angle) {
-    var len = axis.length;
-    final axisStorage = axis._v3storage;
-    var x = axisStorage[0] / len;
-    var y = axisStorage[1] / len;
-    var z = axisStorage[2] / len;
-    var c = Math.cos(angle);
-    var s = Math.sin(angle);
-    var C = 1.0 - c;
-    var m11 = x * x * C + c;
-    var m12 = x * y * C - z * s;
-    var m13 = x * z * C + y * s;
-    var m21 = y * x * C + z * s;
-    var m22 = y * y * C + c;
-    var m23 = y * z * C - x * s;
-    var m31 = z * x * C - y * s;
-    var m32 = z * y * C + x * s;
-    var m33 = z * z * C + c;
-    var t1 = _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31;
-    var t2 = _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31;
-    var t3 = _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31;
-    var t4 = _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31;
-    var t5 = _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32;
-    var t6 = _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32;
-    var t7 = _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32;
-    var t8 = _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32;
-    var t9 = _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33;
-    var t10 = _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33;
-    var t11 = _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33;
-    var t12 = _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33;
+    final double len = axis.length;
+    final Float32List axisStorage = axis._v3storage;
+    final double x = axisStorage[0] / len;
+    final double y = axisStorage[1] / len;
+    final double z = axisStorage[2] / len;
+    final double c = math.cos(angle);
+    final double s = math.sin(angle);
+    final double C = 1.0 - c;
+    final double m11 = x * x * C + c;
+    final double m12 = x * y * C - z * s;
+    final double m13 = x * z * C + y * s;
+    final double m21 = y * x * C + z * s;
+    final double m22 = y * y * C + c;
+    final double m23 = y * z * C - x * s;
+    final double m31 = z * x * C - y * s;
+    final double m32 = z * y * C + x * s;
+    final double m33 = z * z * C + c;
+    final double t1 =
+        _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31;
+    final double t2 =
+        _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31;
+    final double t3 =
+        _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31;
+    final double t4 =
+        _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31;
+    final double t5 =
+        _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32;
+    final double t6 =
+        _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32;
+    final double t7 =
+        _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32;
+    final double t8 =
+        _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32;
+    final double t9 =
+        _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33;
+    final double t10 =
+        _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33;
+    final double t11 =
+        _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33;
+    final double t12 =
+        _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33;
     _m4storage[0] = t1;
     _m4storage[1] = t2;
     _m4storage[2] = t3;
@@ -778,16 +797,16 @@
 
   /// Rotate this [angle] radians around X
   void rotateX(double angle) {
-    double cosAngle = Math.cos(angle);
-    double sinAngle = Math.sin(angle);
-    var t1 = _m4storage[4] * cosAngle + _m4storage[8] * sinAngle;
-    var t2 = _m4storage[5] * cosAngle + _m4storage[9] * sinAngle;
-    var t3 = _m4storage[6] * cosAngle + _m4storage[10] * sinAngle;
-    var t4 = _m4storage[7] * cosAngle + _m4storage[11] * sinAngle;
-    var t5 = _m4storage[4] * -sinAngle + _m4storage[8] * cosAngle;
-    var t6 = _m4storage[5] * -sinAngle + _m4storage[9] * cosAngle;
-    var t7 = _m4storage[6] * -sinAngle + _m4storage[10] * cosAngle;
-    var t8 = _m4storage[7] * -sinAngle + _m4storage[11] * cosAngle;
+    final double cosAngle = math.cos(angle);
+    final double sinAngle = math.sin(angle);
+    final double t1 = _m4storage[4] * cosAngle + _m4storage[8] * sinAngle;
+    final double t2 = _m4storage[5] * cosAngle + _m4storage[9] * sinAngle;
+    final double t3 = _m4storage[6] * cosAngle + _m4storage[10] * sinAngle;
+    final double t4 = _m4storage[7] * cosAngle + _m4storage[11] * sinAngle;
+    final double t5 = _m4storage[4] * -sinAngle + _m4storage[8] * cosAngle;
+    final double t6 = _m4storage[5] * -sinAngle + _m4storage[9] * cosAngle;
+    final double t7 = _m4storage[6] * -sinAngle + _m4storage[10] * cosAngle;
+    final double t8 = _m4storage[7] * -sinAngle + _m4storage[11] * cosAngle;
     _m4storage[4] = t1;
     _m4storage[5] = t2;
     _m4storage[6] = t3;
@@ -800,16 +819,16 @@
 
   /// Rotate this matrix [angle] radians around Y
   void rotateY(double angle) {
-    double cosAngle = Math.cos(angle);
-    double sinAngle = Math.sin(angle);
-    var t1 = _m4storage[0] * cosAngle + _m4storage[8] * -sinAngle;
-    var t2 = _m4storage[1] * cosAngle + _m4storage[9] * -sinAngle;
-    var t3 = _m4storage[2] * cosAngle + _m4storage[10] * -sinAngle;
-    var t4 = _m4storage[3] * cosAngle + _m4storage[11] * -sinAngle;
-    var t5 = _m4storage[0] * sinAngle + _m4storage[8] * cosAngle;
-    var t6 = _m4storage[1] * sinAngle + _m4storage[9] * cosAngle;
-    var t7 = _m4storage[2] * sinAngle + _m4storage[10] * cosAngle;
-    var t8 = _m4storage[3] * sinAngle + _m4storage[11] * cosAngle;
+    final double cosAngle = math.cos(angle);
+    final double sinAngle = math.sin(angle);
+    final double t1 = _m4storage[0] * cosAngle + _m4storage[8] * -sinAngle;
+    final double t2 = _m4storage[1] * cosAngle + _m4storage[9] * -sinAngle;
+    final double t3 = _m4storage[2] * cosAngle + _m4storage[10] * -sinAngle;
+    final double t4 = _m4storage[3] * cosAngle + _m4storage[11] * -sinAngle;
+    final double t5 = _m4storage[0] * sinAngle + _m4storage[8] * cosAngle;
+    final double t6 = _m4storage[1] * sinAngle + _m4storage[9] * cosAngle;
+    final double t7 = _m4storage[2] * sinAngle + _m4storage[10] * cosAngle;
+    final double t8 = _m4storage[3] * sinAngle + _m4storage[11] * cosAngle;
     _m4storage[0] = t1;
     _m4storage[1] = t2;
     _m4storage[2] = t3;
@@ -822,16 +841,16 @@
 
   /// Rotate this matrix [angle] radians around Z
   void rotateZ(double angle) {
-    double cosAngle = Math.cos(angle);
-    double sinAngle = Math.sin(angle);
-    var t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle;
-    var t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle;
-    var t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle;
-    var t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle;
-    var t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle;
-    var t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle;
-    var t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle;
-    var t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle;
+    final double cosAngle = math.cos(angle);
+    final double sinAngle = math.sin(angle);
+    final double t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle;
+    final double t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle;
+    final double t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle;
+    final double t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle;
+    final double t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle;
+    final double t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle;
+    final double t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle;
+    final double t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle;
     _m4storage[0] = t1;
     _m4storage[1] = t2;
     _m4storage[2] = t3;
@@ -843,16 +862,20 @@
   }
 
   /// Scale this matrix by a [Vector3], [Vector4], or x,y,z
-  void scale(x, [double y, double z]) {
+  void scale(dynamic x, [double y, double z]) {
     double sx;
     double sy;
     double sz;
-    double sw = x is Vector4 ? x.w : 1.0;
-    if (x is Vector3 || x is Vector4) {
+    final double sw = x is Vector4 ? x.w : 1.0;
+    if (x is Vector3) {
       sx = x.x;
       sy = x.y;
       sz = x.z;
-    } else {
+    } else if (x is Vector4) {
+      sx = x.x;
+      sy = x.y;
+      sz = x.z;
+    } else if (x is double) {
       sx = x;
       sy = y == null ? x : y.toDouble();
       sz = z == null ? x : z.toDouble();
@@ -877,7 +900,7 @@
 
   /// Create a copy of [this] scaled by a [Vector3], [Vector4] or [x],[y], and
   /// [z].
-  Matrix4 scaled(x, [double y = null, double z = null]) =>
+  Matrix4 scaled(dynamic x, [double y = null, double z = null]) =>
       clone()..scale(x, y, z);
 
   /// Zeros [this].
@@ -947,8 +970,8 @@
 
   /// Returns the component wise absolute value of this.
   Matrix4 absolute() {
-    Matrix4 r = new Matrix4.zero();
-    final rStorage = r._m4storage;
+    final Matrix4 r = new Matrix4.zero();
+    final Float32List rStorage = r._m4storage;
     rStorage[0] = _m4storage[0].abs();
     rStorage[1] = _m4storage[1].abs();
     rStorage[2] = _m4storage[2].abs();
@@ -970,28 +993,28 @@
 
   /// Returns the determinant of this matrix.
   double determinant() {
-    double det2_01_01 =
+    final double det2_01_01 =
         _m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4];
-    double det2_01_02 =
+    final double det2_01_02 =
         _m4storage[0] * _m4storage[6] - _m4storage[2] * _m4storage[4];
-    double det2_01_03 =
+    final double det2_01_03 =
         _m4storage[0] * _m4storage[7] - _m4storage[3] * _m4storage[4];
-    double det2_01_12 =
+    final double det2_01_12 =
         _m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5];
-    double det2_01_13 =
+    final double det2_01_13 =
         _m4storage[1] * _m4storage[7] - _m4storage[3] * _m4storage[5];
-    double det2_01_23 =
+    final double det2_01_23 =
         _m4storage[2] * _m4storage[7] - _m4storage[3] * _m4storage[6];
-    double det3_201_012 = _m4storage[8] * det2_01_12 -
+    final double det3_201_012 = _m4storage[8] * det2_01_12 -
         _m4storage[9] * det2_01_02 +
         _m4storage[10] * det2_01_01;
-    double det3_201_013 = _m4storage[8] * det2_01_13 -
+    final double det3_201_013 = _m4storage[8] * det2_01_13 -
         _m4storage[9] * det2_01_03 +
         _m4storage[11] * det2_01_01;
-    double det3_201_023 = _m4storage[8] * det2_01_23 -
+    final double det3_201_023 = _m4storage[8] * det2_01_23 -
         _m4storage[10] * det2_01_03 +
         _m4storage[11] * det2_01_02;
-    double det3_201_123 = _m4storage[9] * det2_01_23 -
+    final double det3_201_123 = _m4storage[9] * det2_01_23 -
         _m4storage[10] * det2_01_13 +
         _m4storage[11] * det2_01_12;
     return -det3_201_123 * _m4storage[12] +
@@ -1002,7 +1025,7 @@
 
   /// Returns the dot product of row [i] and [v].
   double dotRow(int i, Vector4 v) {
-    final vStorage = v._v4storage;
+    final Float32List vStorage = v._v4storage;
     return _m4storage[i] * vStorage[0] +
         _m4storage[4 + i] * vStorage[1] +
         _m4storage[8 + i] * vStorage[2] +
@@ -1011,7 +1034,7 @@
 
   /// Returns the dot product of column [j] and [v].
   double dotColumn(int j, Vector4 v) {
-    final vStorage = v._v4storage;
+    final Float32List vStorage = v._v4storage;
     return _m4storage[j * 4] * vStorage[0] +
         _m4storage[j * 4 + 1] * vStorage[1] +
         _m4storage[j * 4 + 2] * vStorage[2] +
@@ -1069,34 +1092,34 @@
 
   /// Returns relative error between [this] and [correct]
   double relativeError(Matrix4 correct) {
-    Matrix4 diff = correct - this;
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = diff.infinityNorm();
+    final Matrix4 diff = correct - this;
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = diff.infinityNorm();
     return diff_norm / correct_norm;
   }
 
   /// Returns absolute error between [this] and [correct]
   double absoluteError(Matrix4 correct) {
-    double this_norm = infinityNorm();
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = (this_norm - correct_norm).abs();
+    final double this_norm = infinityNorm();
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = (this_norm - correct_norm).abs();
     return diff_norm;
   }
 
   /// Returns the translation vector from this homogeneous transformation matrix.
   Vector3 getTranslation() {
-    double z = _m4storage[14];
-    double y = _m4storage[13];
-    double x = _m4storage[12];
+    final double z = _m4storage[14];
+    final double y = _m4storage[13];
+    final double x = _m4storage[12];
     return new Vector3(x, y, z);
   }
 
   /// Sets the translation vector in this homogeneous transformation matrix.
   void setTranslation(Vector3 t) {
-    final tStorage = t._v3storage;
-    double z = tStorage[2];
-    double y = tStorage[1];
-    double x = tStorage[0];
+    final Float32List tStorage = t._v3storage;
+    final double z = tStorage[2];
+    final double y = tStorage[1];
+    final double x = tStorage[0];
     _m4storage[14] = z;
     _m4storage[13] = y;
     _m4storage[12] = x;
@@ -1111,7 +1134,7 @@
 
   /// Returns the rotation matrix from this homogeneous transformation matrix.
   Matrix3 getRotation() {
-    Matrix3 r = new Matrix3.zero();
+    final Matrix3 r = new Matrix3.zero();
     copyRotation(r);
     return r;
   }
@@ -1119,7 +1142,7 @@
   /// Copies the rotation matrix from this homogeneous transformation matrix
   /// into [rotation].
   void copyRotation(Matrix3 rotation) {
-    final rStorage = rotation._m3storage;
+    final Float32List rStorage = rotation._m3storage;
     rStorage[0] = _m4storage[0];
     rStorage[1] = _m4storage[1];
     rStorage[2] = _m4storage[2];
@@ -1133,7 +1156,7 @@
 
   /// Sets the rotation matrix in this homogeneous transformation matrix.
   void setRotation(Matrix3 r) {
-    final rStorage = r._m3storage;
+    final Float32List rStorage = r._m3storage;
     _m4storage[0] = rStorage[0];
     _m4storage[1] = rStorage[1];
     _m4storage[2] = rStorage[2];
@@ -1151,16 +1174,16 @@
 
   /// Returns the max scale value of the 3 axes.
   double getMaxScaleOnAxis() {
-    final scaleXSq = _m4storage[0] * _m4storage[0] +
+    final double scaleXSq = _m4storage[0] * _m4storage[0] +
         _m4storage[1] * _m4storage[1] +
         _m4storage[2] * _m4storage[2];
-    final scaleYSq = _m4storage[4] * _m4storage[4] +
+    final double scaleYSq = _m4storage[4] * _m4storage[4] +
         _m4storage[5] * _m4storage[5] +
         _m4storage[6] * _m4storage[6];
-    final scaleZSq = _m4storage[8] * _m4storage[8] +
+    final double scaleZSq = _m4storage[8] * _m4storage[8] +
         _m4storage[9] * _m4storage[9] +
         _m4storage[10] * _m4storage[10];
-    return Math.sqrt(Math.max(scaleXSq, Math.max(scaleYSq, scaleZSq)));
+    return math.sqrt(math.max(scaleXSq, math.max(scaleYSq, scaleZSq)));
   }
 
   /// Transposes just the upper 3x3 rotation matrix.
@@ -1191,42 +1214,42 @@
 
   /// Set this matrix to be the inverse of [arg]
   double copyInverse(Matrix4 arg) {
-    final argStorage = arg._m4storage;
-    double a00 = argStorage[0];
-    double a01 = argStorage[1];
-    double a02 = argStorage[2];
-    double a03 = argStorage[3];
-    double a10 = argStorage[4];
-    double a11 = argStorage[5];
-    double a12 = argStorage[6];
-    double a13 = argStorage[7];
-    double a20 = argStorage[8];
-    double a21 = argStorage[9];
-    double a22 = argStorage[10];
-    double a23 = argStorage[11];
-    double a30 = argStorage[12];
-    double a31 = argStorage[13];
-    double a32 = argStorage[14];
-    double a33 = argStorage[15];
-    var b00 = a00 * a11 - a01 * a10;
-    var b01 = a00 * a12 - a02 * a10;
-    var b02 = a00 * a13 - a03 * a10;
-    var b03 = a01 * a12 - a02 * a11;
-    var b04 = a01 * a13 - a03 * a11;
-    var b05 = a02 * a13 - a03 * a12;
-    var b06 = a20 * a31 - a21 * a30;
-    var b07 = a20 * a32 - a22 * a30;
-    var b08 = a20 * a33 - a23 * a30;
-    var b09 = a21 * a32 - a22 * a31;
-    var b10 = a21 * a33 - a23 * a31;
-    var b11 = a22 * a33 - a23 * a32;
-    var det =
+    final Float32List argStorage = arg._m4storage;
+    final double a00 = argStorage[0];
+    final double a01 = argStorage[1];
+    final double a02 = argStorage[2];
+    final double a03 = argStorage[3];
+    final double a10 = argStorage[4];
+    final double a11 = argStorage[5];
+    final double a12 = argStorage[6];
+    final double a13 = argStorage[7];
+    final double a20 = argStorage[8];
+    final double a21 = argStorage[9];
+    final double a22 = argStorage[10];
+    final double a23 = argStorage[11];
+    final double a30 = argStorage[12];
+    final double a31 = argStorage[13];
+    final double a32 = argStorage[14];
+    final double a33 = argStorage[15];
+    final double b00 = a00 * a11 - a01 * a10;
+    final double b01 = a00 * a12 - a02 * a10;
+    final double b02 = a00 * a13 - a03 * a10;
+    final double b03 = a01 * a12 - a02 * a11;
+    final double b04 = a01 * a13 - a03 * a11;
+    final double b05 = a02 * a13 - a03 * a12;
+    final double b06 = a20 * a31 - a21 * a30;
+    final double b07 = a20 * a32 - a22 * a30;
+    final double b08 = a20 * a33 - a23 * a30;
+    final double b09 = a21 * a32 - a22 * a31;
+    final double b10 = a21 * a33 - a23 * a31;
+    final double b11 = a22 * a33 - a23 * a32;
+    final double det =
         (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
     if (det == 0.0) {
       setFrom(arg);
       return 0.0;
     }
-    var invDet = 1.0 / det;
+    final double invDet = 1.0 / det;
     _m4storage[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
     _m4storage[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
     _m4storage[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
@@ -1247,11 +1270,11 @@
   }
 
   double invertRotation() {
-    double det = determinant();
+    final double det = determinant();
     if (det == 0.0) {
       return 0.0;
     }
-    double invDet = 1.0 / det;
+    final double invDet = 1.0 / det;
     double ix;
     double iy;
     double iz;
@@ -1293,8 +1316,8 @@
 
   /// Sets the upper 3x3 to a rotation of [radians] around X
   void setRotationX(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m4storage[0] = 1.0;
     _m4storage[1] = 0.0;
     _m4storage[2] = 0.0;
@@ -1311,8 +1334,8 @@
 
   /// Sets the upper 3x3 to a rotation of [radians] around Y
   void setRotationY(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m4storage[0] = c;
     _m4storage[1] = 0.0;
     _m4storage[2] = -s;
@@ -1329,8 +1352,8 @@
 
   /// Sets the upper 3x3 to a rotation of [radians] around Z
   void setRotationZ(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m4storage[0] = c;
     _m4storage[1] = s;
     _m4storage[2] = 0.0;
@@ -1348,22 +1371,22 @@
   /// Converts into Adjugate matrix and scales by [scale]
   void scaleAdjoint(double scale) {
     // Adapted from code by Richard Carling.
-    double a1 = _m4storage[0];
-    double b1 = _m4storage[4];
-    double c1 = _m4storage[8];
-    double d1 = _m4storage[12];
-    double a2 = _m4storage[1];
-    double b2 = _m4storage[5];
-    double c2 = _m4storage[9];
-    double d2 = _m4storage[13];
-    double a3 = _m4storage[2];
-    double b3 = _m4storage[6];
-    double c3 = _m4storage[10];
-    double d3 = _m4storage[14];
-    double a4 = _m4storage[3];
-    double b4 = _m4storage[7];
-    double c4 = _m4storage[11];
-    double d4 = _m4storage[15];
+    final double a1 = _m4storage[0];
+    final double b1 = _m4storage[4];
+    final double c1 = _m4storage[8];
+    final double d1 = _m4storage[12];
+    final double a2 = _m4storage[1];
+    final double b2 = _m4storage[5];
+    final double c2 = _m4storage[9];
+    final double d2 = _m4storage[13];
+    final double a3 = _m4storage[2];
+    final double b3 = _m4storage[6];
+    final double c3 = _m4storage[10];
+    final double d3 = _m4storage[14];
+    final double a4 = _m4storage[3];
+    final double b4 = _m4storage[7];
+    final double c4 = _m4storage[11];
+    final double d4 = _m4storage[15];
     _m4storage[0] = (b2 * (c3 * d4 - c4 * d3) -
             c2 * (b3 * d4 - b4 * d3) +
             d2 * (b3 * c4 - b4 * c3)) *
@@ -1434,19 +1457,19 @@
   /// Returns [arg].
   /// Primarily used by AABB transformation code.
   Vector3 absoluteRotate(Vector3 arg) {
-    double m00 = _m4storage[0].abs();
-    double m01 = _m4storage[4].abs();
-    double m02 = _m4storage[8].abs();
-    double m10 = _m4storage[1].abs();
-    double m11 = _m4storage[5].abs();
-    double m12 = _m4storage[9].abs();
-    double m20 = _m4storage[2].abs();
-    double m21 = _m4storage[6].abs();
-    double m22 = _m4storage[10].abs();
-    final argStorage = arg._v3storage;
-    double x = argStorage[0];
-    double y = argStorage[1];
-    double z = argStorage[2];
+    final double m00 = _m4storage[0].abs();
+    final double m01 = _m4storage[4].abs();
+    final double m02 = _m4storage[8].abs();
+    final double m10 = _m4storage[1].abs();
+    final double m11 = _m4storage[5].abs();
+    final double m12 = _m4storage[9].abs();
+    final double m20 = _m4storage[2].abs();
+    final double m21 = _m4storage[6].abs();
+    final double m22 = _m4storage[10].abs();
+    final Float32List argStorage = arg._v3storage;
+    final double x = argStorage[0];
+    final double y = argStorage[1];
+    final double z = argStorage[2];
     argStorage[0] = x * m00 + y * m01 + z * m02 + 0.0 * 0.0;
     argStorage[1] = x * m10 + y * m11 + z * m12 + 0.0 * 0.0;
     argStorage[2] = x * m20 + y * m21 + z * m22 + 0.0 * 0.0;
@@ -1455,7 +1478,7 @@
 
   /// Adds [o] to [this].
   void add(Matrix4 o) {
-    final oStorage = o._m4storage;
+    final Float32List oStorage = o._m4storage;
     _m4storage[0] = _m4storage[0] + oStorage[0];
     _m4storage[1] = _m4storage[1] + oStorage[1];
     _m4storage[2] = _m4storage[2] + oStorage[2];
@@ -1476,7 +1499,7 @@
 
   /// Subtracts [o] from [this].
   void sub(Matrix4 o) {
-    final oStorage = o._m4storage;
+    final Float32List oStorage = o._m4storage;
     _m4storage[0] = _m4storage[0] - oStorage[0];
     _m4storage[1] = _m4storage[1] - oStorage[1];
     _m4storage[2] = _m4storage[2] - oStorage[2];
@@ -1517,39 +1540,39 @@
 
   /// Multiply [this] by [arg].
   void multiply(Matrix4 arg) {
-    final m00 = _m4storage[0];
-    final m01 = _m4storage[4];
-    final m02 = _m4storage[8];
-    final m03 = _m4storage[12];
-    final m10 = _m4storage[1];
-    final m11 = _m4storage[5];
-    final m12 = _m4storage[9];
-    final m13 = _m4storage[13];
-    final m20 = _m4storage[2];
-    final m21 = _m4storage[6];
-    final m22 = _m4storage[10];
-    final m23 = _m4storage[14];
-    final m30 = _m4storage[3];
-    final m31 = _m4storage[7];
-    final m32 = _m4storage[11];
-    final m33 = _m4storage[15];
-    final argStorage = arg._m4storage;
-    final n00 = argStorage[0];
-    final n01 = argStorage[4];
-    final n02 = argStorage[8];
-    final n03 = argStorage[12];
-    final n10 = argStorage[1];
-    final n11 = argStorage[5];
-    final n12 = argStorage[9];
-    final n13 = argStorage[13];
-    final n20 = argStorage[2];
-    final n21 = argStorage[6];
-    final n22 = argStorage[10];
-    final n23 = argStorage[14];
-    final n30 = argStorage[3];
-    final n31 = argStorage[7];
-    final n32 = argStorage[11];
-    final n33 = argStorage[15];
+    final double m00 = _m4storage[0];
+    final double m01 = _m4storage[4];
+    final double m02 = _m4storage[8];
+    final double m03 = _m4storage[12];
+    final double m10 = _m4storage[1];
+    final double m11 = _m4storage[5];
+    final double m12 = _m4storage[9];
+    final double m13 = _m4storage[13];
+    final double m20 = _m4storage[2];
+    final double m21 = _m4storage[6];
+    final double m22 = _m4storage[10];
+    final double m23 = _m4storage[14];
+    final double m30 = _m4storage[3];
+    final double m31 = _m4storage[7];
+    final double m32 = _m4storage[11];
+    final double m33 = _m4storage[15];
+    final Float32List argStorage = arg._m4storage;
+    final double n00 = argStorage[0];
+    final double n01 = argStorage[4];
+    final double n02 = argStorage[8];
+    final double n03 = argStorage[12];
+    final double n10 = argStorage[1];
+    final double n11 = argStorage[5];
+    final double n12 = argStorage[9];
+    final double n13 = argStorage[13];
+    final double n20 = argStorage[2];
+    final double n21 = argStorage[6];
+    final double n22 = argStorage[10];
+    final double n23 = argStorage[14];
+    final double n30 = argStorage[3];
+    final double n31 = argStorage[7];
+    final double n32 = argStorage[11];
+    final double n33 = argStorage[15];
     _m4storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30);
     _m4storage[4] = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31);
     _m4storage[8] = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32);
@@ -1573,23 +1596,23 @@
 
   /// Multiply a transposed [this] with [arg].
   void transposeMultiply(Matrix4 arg) {
-    double m00 = _m4storage[0];
-    double m01 = _m4storage[1];
-    double m02 = _m4storage[2];
-    double m03 = _m4storage[3];
-    double m10 = _m4storage[4];
-    double m11 = _m4storage[5];
-    double m12 = _m4storage[6];
-    double m13 = _m4storage[7];
-    double m20 = _m4storage[8];
-    double m21 = _m4storage[9];
-    double m22 = _m4storage[10];
-    double m23 = _m4storage[11];
-    double m30 = _m4storage[12];
-    double m31 = _m4storage[13];
-    double m32 = _m4storage[14];
-    double m33 = _m4storage[15];
-    final argStorage = arg._m4storage;
+    final double m00 = _m4storage[0];
+    final double m01 = _m4storage[1];
+    final double m02 = _m4storage[2];
+    final double m03 = _m4storage[3];
+    final double m10 = _m4storage[4];
+    final double m11 = _m4storage[5];
+    final double m12 = _m4storage[6];
+    final double m13 = _m4storage[7];
+    final double m20 = _m4storage[8];
+    final double m21 = _m4storage[9];
+    final double m22 = _m4storage[10];
+    final double m23 = _m4storage[11];
+    final double m30 = _m4storage[12];
+    final double m31 = _m4storage[13];
+    final double m32 = _m4storage[14];
+    final double m33 = _m4storage[15];
+    final Float32List argStorage = arg._m4storage;
     _m4storage[0] = (m00 * argStorage[0]) +
         (m01 * argStorage[1]) +
         (m02 * argStorage[2]) +
@@ -1658,23 +1681,23 @@
 
   /// Multiply [this] with a transposed [arg].
   void multiplyTranspose(Matrix4 arg) {
-    double m00 = _m4storage[0];
-    double m01 = _m4storage[4];
-    double m02 = _m4storage[8];
-    double m03 = _m4storage[12];
-    double m10 = _m4storage[1];
-    double m11 = _m4storage[5];
-    double m12 = _m4storage[9];
-    double m13 = _m4storage[13];
-    double m20 = _m4storage[2];
-    double m21 = _m4storage[6];
-    double m22 = _m4storage[10];
-    double m23 = _m4storage[14];
-    double m30 = _m4storage[3];
-    double m31 = _m4storage[7];
-    double m32 = _m4storage[11];
-    double m33 = _m4storage[15];
-    final argStorage = arg._m4storage;
+    final double m00 = _m4storage[0];
+    final double m01 = _m4storage[4];
+    final double m02 = _m4storage[8];
+    final double m03 = _m4storage[12];
+    final double m10 = _m4storage[1];
+    final double m11 = _m4storage[5];
+    final double m12 = _m4storage[9];
+    final double m13 = _m4storage[13];
+    final double m20 = _m4storage[2];
+    final double m21 = _m4storage[6];
+    final double m22 = _m4storage[10];
+    final double m23 = _m4storage[14];
+    final double m30 = _m4storage[3];
+    final double m31 = _m4storage[7];
+    final double m32 = _m4storage[11];
+    final double m33 = _m4storage[15];
+    final Float32List argStorage = arg._m4storage;
     _m4storage[0] = (m00 * argStorage[0]) +
         (m01 * argStorage[4]) +
         (m02 * argStorage[8]) +
@@ -1743,23 +1766,27 @@
 
   /// Decomposes [this] into [translation], [rotation] and [scale] components.
   void decompose(Vector3 translation, Quaternion rotation, Vector3 scale) {
-    final v = new Vector3.zero();
-    var sx = (v..setValues(_m4storage[0], _m4storage[1], _m4storage[2])).length;
-    var sy = (v..setValues(_m4storage[4], _m4storage[5], _m4storage[6])).length;
-    var sz =
+    final Vector3 v = new Vector3.zero();
+    double sx =
+        (v..setValues(_m4storage[0], _m4storage[1], _m4storage[2])).length;
+    final double sy =
+        (v..setValues(_m4storage[4], _m4storage[5], _m4storage[6])).length;
+    final double sz =
         (v..setValues(_m4storage[8], _m4storage[9], _m4storage[10])).length;
 
-    if (determinant() < 0) sx = -sx;
+    if (determinant() < 0) {
+      sx = -sx;
+    }
 
     translation._v3storage[0] = _m4storage[12];
     translation._v3storage[1] = _m4storage[13];
     translation._v3storage[2] = _m4storage[14];
 
-    final invSX = 1.0 / sx;
-    final invSY = 1.0 / sy;
-    final invSZ = 1.0 / sz;
+    final double invSX = 1.0 / sx;
+    final double invSY = 1.0 / sy;
+    final double invSZ = 1.0 / sz;
 
-    final m = new Matrix4.copy(this);
+    final Matrix4 m = new Matrix4.copy(this);
     m._m4storage[0] *= invSX;
     m._m4storage[1] *= invSX;
     m._m4storage[2] *= invSX;
@@ -1779,14 +1806,14 @@
 
   /// Rotate [arg] of type [Vector3] using the rotation defined by [this].
   Vector3 rotate3(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float32List argStorage = arg._v3storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]);
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]);
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]);
     argStorage[0] = x_;
@@ -1809,16 +1836,16 @@
   /// Transform [arg] of type [Vector3] using the transformation defined by
   /// [this].
   Vector3 transform3(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float32List argStorage = arg._v3storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]) +
         _m4storage[12];
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]) +
         _m4storage[13];
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]) +
         _m4storage[14];
@@ -1843,20 +1870,20 @@
   /// Transform [arg] of type [Vector4] using the transformation defined by
   /// [this].
   Vector4 transform(Vector4 arg) {
-    final argStorage = arg._v4storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float32List argStorage = arg._v4storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]) +
         (_m4storage[12] * argStorage[3]);
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]) +
         (_m4storage[13] * argStorage[3]);
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]) +
         (_m4storage[14] * argStorage[3]);
-    final w_ = (_m4storage[3] * argStorage[0]) +
+    final double w_ = (_m4storage[3] * argStorage[0]) +
         (_m4storage[7] * argStorage[1]) +
         (_m4storage[11] * argStorage[2]) +
         (_m4storage[15] * argStorage[3]);
@@ -1870,20 +1897,20 @@
   /// Transform [arg] of type [Vector3] using the perspective transformation
   /// defined by [this].
   Vector3 perspectiveTransform(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float32List argStorage = arg._v3storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]) +
         _m4storage[12];
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]) +
         _m4storage[13];
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]) +
         _m4storage[14];
-    final w_ = 1.0 /
+    final double w_ = 1.0 /
         ((_m4storage[3] * argStorage[0]) +
             (_m4storage[7] * argStorage[1]) +
             (_m4storage[11] * argStorage[2]) +
@@ -1908,7 +1935,7 @@
 
   /// Copies [this] into [array] starting at [offset].
   void copyIntoArray(List<num> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     array[i + 15] = _m4storage[15];
     array[i + 14] = _m4storage[14];
     array[i + 13] = _m4storage[13];
@@ -1929,7 +1956,7 @@
 
   /// Copies elements from [array] into [this] starting at [offset].
   void copyFromArray(List<double> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     _m4storage[15] = array[i + 15];
     _m4storage[14] = array[i + 14];
     _m4storage[13] = array[i + 13];
@@ -1950,8 +1977,8 @@
 
   /// Multiply [this] to each set of xyz values in [array] starting at [offset].
   List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
-    for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
-      final v = new Vector3.array(array, j)..applyMatrix4(this);
+    for (int i = 0, j = offset; i < array.length; i += 3, j += 3) {
+      final Vector3 v = new Vector3.array(array, j)..applyMatrix4(this);
       array[j] = v.storage[0];
       array[j + 1] = v.storage[1];
       array[j + 2] = v.storage[2];
@@ -1961,63 +1988,69 @@
   }
 
   Vector3 get right {
-    double x = _m4storage[0];
-    double y = _m4storage[1];
-    double z = _m4storage[2];
+    final double x = _m4storage[0];
+    final double y = _m4storage[1];
+    final double z = _m4storage[2];
     return new Vector3(x, y, z);
   }
 
   Vector3 get up {
-    double x = _m4storage[4];
-    double y = _m4storage[5];
-    double z = _m4storage[6];
+    final double x = _m4storage[4];
+    final double y = _m4storage[5];
+    final double z = _m4storage[6];
     return new Vector3(x, y, z);
   }
 
   Vector3 get forward {
-    double x = _m4storage[8];
-    double y = _m4storage[9];
-    double z = _m4storage[10];
+    final double x = _m4storage[8];
+    final double y = _m4storage[9];
+    final double z = _m4storage[10];
     return new Vector3(x, y, z);
   }
 
   /// Is [this] the identity matrix?
-  bool isIdentity() {
-    return _m4storage[0] == 1.0 // col 1
-        && _m4storage[1] == 0.0
-        && _m4storage[2] == 0.0
-        && _m4storage[3] == 0.0
-        && _m4storage[4] == 0.0 // col 2
-        && _m4storage[5] == 1.0
-        && _m4storage[6] == 0.0
-        && _m4storage[7] == 0.0
-        && _m4storage[8] == 0.0 // col 3
-        && _m4storage[9] == 0.0
-        && _m4storage[10] == 1.0
-        && _m4storage[11] == 0.0
-        && _m4storage[12] == 0.0 // col 4
-        && _m4storage[13] == 0.0
-        && _m4storage[14] == 0.0
-        && _m4storage[15] == 1.0;
-  }
+  bool isIdentity() =>
+      _m4storage[0] == 1.0 // col 1
+      &&
+      _m4storage[1] == 0.0 &&
+      _m4storage[2] == 0.0 &&
+      _m4storage[3] == 0.0 &&
+      _m4storage[4] == 0.0 // col 2
+      &&
+      _m4storage[5] == 1.0 &&
+      _m4storage[6] == 0.0 &&
+      _m4storage[7] == 0.0 &&
+      _m4storage[8] == 0.0 // col 3
+      &&
+      _m4storage[9] == 0.0 &&
+      _m4storage[10] == 1.0 &&
+      _m4storage[11] == 0.0 &&
+      _m4storage[12] == 0.0 // col 4
+      &&
+      _m4storage[13] == 0.0 &&
+      _m4storage[14] == 0.0 &&
+      _m4storage[15] == 1.0;
 
   /// Is [this] the zero matrix?
-  bool isZero() {
-    return _m4storage[0] == 0.0 // col 1
-        && _m4storage[1] == 0.0
-        && _m4storage[2] == 0.0
-        && _m4storage[3] == 0.0
-        && _m4storage[4] == 0.0 // col 2
-        && _m4storage[5] == 0.0
-        && _m4storage[6] == 0.0
-        && _m4storage[7] == 0.0
-        && _m4storage[8] == 0.0 // col 3
-        && _m4storage[9] == 0.0
-        && _m4storage[10] == 0.0
-        && _m4storage[11] == 0.0
-        && _m4storage[12] == 0.0 // col 4
-        && _m4storage[13] == 0.0
-        && _m4storage[14] == 0.0
-        && _m4storage[15] == 0.0;
-  }
+  bool isZero() =>
+      _m4storage[0] == 0.0 // col 1
+      &&
+      _m4storage[1] == 0.0 &&
+      _m4storage[2] == 0.0 &&
+      _m4storage[3] == 0.0 &&
+      _m4storage[4] == 0.0 // col 2
+      &&
+      _m4storage[5] == 0.0 &&
+      _m4storage[6] == 0.0 &&
+      _m4storage[7] == 0.0 &&
+      _m4storage[8] == 0.0 // col 3
+      &&
+      _m4storage[9] == 0.0 &&
+      _m4storage[10] == 0.0 &&
+      _m4storage[11] == 0.0 &&
+      _m4storage[12] == 0.0 // col 4
+      &&
+      _m4storage[13] == 0.0 &&
+      _m4storage[14] == 0.0 &&
+      _m4storage[15] == 0.0;
 }
diff --git a/pub/vector_math/lib/src/vector_math/obb3.dart b/pub/vector_math/lib/src/vector_math/obb3.dart
index d331d8d..47642c4 100644
--- a/pub/vector_math/lib/src/vector_math/obb3.dart
+++ b/pub/vector_math/lib/src/vector_math/obb3.dart
@@ -84,23 +84,29 @@
 
   /// Rotate [this] by the rotation matrix [t].
   void rotate(Matrix3 t) {
-    t.transform(_axis0..scale(_halfExtents.x));
-    t.transform(_axis1..scale(_halfExtents.y));
-    t.transform(_axis2..scale(_halfExtents.z));
-    _halfExtents.x = _axis0.normalize();
-    _halfExtents.y = _axis1.normalize();
-    _halfExtents.z = _axis2.normalize();
+    t
+      ..transform(_axis0..scale(_halfExtents.x))
+      ..transform(_axis1..scale(_halfExtents.y))
+      ..transform(_axis2..scale(_halfExtents.z));
+
+    _halfExtents
+      ..x = _axis0.normalize()
+      ..y = _axis1.normalize()
+      ..z = _axis2.normalize();
   }
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    t.transform3(_center);
-    t.rotate3(_axis0..scale(_halfExtents.x));
-    t.rotate3(_axis1..scale(_halfExtents.y));
-    t.rotate3(_axis2..scale(_halfExtents.z));
-    _halfExtents.x = _axis0.normalize();
-    _halfExtents.y = _axis1.normalize();
-    _halfExtents.z = _axis2.normalize();
+    t
+      ..transform3(_center)
+      ..rotate3(_axis0..scale(_halfExtents.x))
+      ..rotate3(_axis1..scale(_halfExtents.y))
+      ..rotate3(_axis2..scale(_halfExtents.z));
+
+    _halfExtents
+      ..x = _axis0.normalize()
+      ..y = _axis1.normalize()
+      ..z = _axis2.normalize();
   }
 
   /// Store the corner with [cornerIndex] in [corner].
@@ -163,40 +169,41 @@
 
   /// Find the closest point [q] on the OBB to the point [p] and store it in [q].
   void closestPointTo(Vector3 p, Vector3 q) {
-    final d = p - _center;
+    final Vector3 d = p - _center;
 
     q.setFrom(_center);
 
-    var dist = d.dot(_axis0);
-    dist = dist.clamp(-_halfExtents.x, _halfExtents.x);
+    double dist = d.dot(_axis0);
+    dist = dist.clamp(-_halfExtents.x, _halfExtents.x).toDouble();
     q.addScaled(_axis0, dist);
 
     dist = d.dot(_axis1);
-    dist = dist.clamp(-_halfExtents.y, _halfExtents.y);
+    dist = dist.clamp(-_halfExtents.y, _halfExtents.y).toDouble();
     q.addScaled(_axis1, dist);
 
     dist = d.dot(_axis2);
-    dist = dist.clamp(-_halfExtents.z, _halfExtents.z);
+    dist = dist.clamp(-_halfExtents.z, _halfExtents.z).toDouble();
     q.addScaled(_axis2, dist);
   }
 
   // Avoid allocating these instance on every call to intersectsWithObb3
-  static final _r = new Matrix3.zero();
-  static final _absR = new Matrix3.zero();
-  static final _t = new Vector3.zero();
+  static final Matrix3 _r = new Matrix3.zero();
+  static final Matrix3 _absR = new Matrix3.zero();
+  static final Vector3 _t = new Vector3.zero();
 
   /// Check for intersection between [this] and [other].
   bool intersectsWithObb3(Obb3 other, [double epsilon = 1e-3]) {
     // Compute rotation matrix expressing other in this's coordinate frame
-    _r.setEntry(0, 0, _axis0.dot(other._axis0));
-    _r.setEntry(1, 0, _axis1.dot(other._axis0));
-    _r.setEntry(2, 0, _axis2.dot(other._axis0));
-    _r.setEntry(0, 1, _axis0.dot(other._axis1));
-    _r.setEntry(1, 1, _axis1.dot(other._axis1));
-    _r.setEntry(2, 1, _axis2.dot(other._axis1));
-    _r.setEntry(0, 2, _axis0.dot(other._axis2));
-    _r.setEntry(1, 2, _axis1.dot(other._axis2));
-    _r.setEntry(2, 2, _axis2.dot(other._axis2));
+    _r
+      ..setEntry(0, 0, _axis0.dot(other._axis0))
+      ..setEntry(1, 0, _axis1.dot(other._axis0))
+      ..setEntry(2, 0, _axis2.dot(other._axis0))
+      ..setEntry(0, 1, _axis0.dot(other._axis1))
+      ..setEntry(1, 1, _axis1.dot(other._axis1))
+      ..setEntry(2, 1, _axis2.dot(other._axis1))
+      ..setEntry(0, 2, _axis0.dot(other._axis2))
+      ..setEntry(1, 2, _axis1.dot(other._axis2))
+      ..setEntry(2, 2, _axis2.dot(other._axis2));
 
     // Compute translation vector t
     _t
@@ -209,8 +216,8 @@
     // Compute common subexpressions. Add in an epsilon term to
     // counteract arithmetic errors when two edges are parallel and
     // their cross product is (near) null.
-    for (var i = 0; i < 3; i++) {
-      for (var j = 0; j < 3; j++) {
+    for (int i = 0; i < 3; i++) {
+      for (int j = 0; j < 3; j++) {
         _absR.setEntry(i, j, _r.entry(i, j).abs() + epsilon);
       }
     }
@@ -219,7 +226,7 @@
     double rb;
 
     // Test axes L = A0, L = A1, L = A2
-    for (var i = 0; i < 3; i++) {
+    for (int i = 0; i < 3; i++) {
       ra = _halfExtents[i];
       rb = other._halfExtents[0] * _absR.entry(i, 0) +
           other._halfExtents[1] * _absR.entry(i, 1) +
@@ -231,7 +238,7 @@
     }
 
     // Test axes L = B0, L = B1, L = B2
-    for (var i = 0; i < 3; i++) {
+    for (int i = 0; i < 3; i++) {
       ra = _halfExtents[0] * _absR.entry(0, i) +
           _halfExtents[1] * _absR.entry(1, i) +
           _halfExtents[2] * _absR.entry(2, i);
@@ -332,23 +339,26 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _triangle = new Triangle();
-  static final _aabb3 = new Aabb3();
-  static final _zeroVector = new Vector3.zero();
+  static final Triangle _triangle = new Triangle();
+  static final Aabb3 _aabb3 = new Aabb3();
+  static final Vector3 _zeroVector = new Vector3.zero();
 
   /// Return if [this] intersects with [other]
   bool intersectsWithTriangle(Triangle other, {IntersectionResult result}) {
     _triangle.copyFrom(other);
 
-    _triangle.point0.sub(_center);
-    _triangle.point0.setValues(_triangle.point0.dot(axis0),
-        _triangle.point0.dot(axis1), _triangle.point0.dot(axis2));
-    _triangle.point1.sub(_center);
-    _triangle.point1.setValues(_triangle.point1.dot(axis0),
-        _triangle.point1.dot(axis1), _triangle.point1.dot(axis2));
-    _triangle.point2.sub(_center);
-    _triangle.point2.setValues(_triangle.point2.dot(axis0),
-        _triangle.point2.dot(axis1), _triangle.point2.dot(axis2));
+    _triangle.point0
+      ..sub(_center)
+      ..setValues(_triangle.point0.dot(axis0), _triangle.point0.dot(axis1),
+          _triangle.point0.dot(axis2));
+    _triangle.point1
+      ..sub(_center)
+      ..setValues(_triangle.point1.dot(axis0), _triangle.point1.dot(axis1),
+          _triangle.point1.dot(axis2));
+    _triangle.point2
+      ..sub(_center)
+      ..setValues(_triangle.point2.dot(axis0), _triangle.point2.dot(axis1),
+          _triangle.point2.dot(axis2));
 
     _aabb3.setCenterAndHalfExtents(_zeroVector, _halfExtents);
 
@@ -356,15 +366,14 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithVector3
-  static final _vector = new Vector3.zero();
+  static final Vector3 _vector = new Vector3.zero();
 
   /// Return if [this] intersects with [other]
   bool intersectsWithVector3(Vector3 other) {
-    _vector.setFrom(other);
-
-    _vector.sub(_center);
-    _vector.setValues(
-        _vector.dot(axis0), _vector.dot(axis1), _vector.dot(axis2));
+    _vector
+      ..setFrom(other)
+      ..sub(_center)
+      ..setValues(_vector.dot(axis0), _vector.dot(axis1), _vector.dot(axis2));
 
     _aabb3.setCenterAndHalfExtents(_zeroVector, _halfExtents);
 
@@ -372,8 +381,8 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _quadTriangle0 = new Triangle();
-  static final _quadTriangle1 = new Triangle();
+  static final Triangle _quadTriangle0 = new Triangle();
+  static final Triangle _quadTriangle1 = new Triangle();
 
   /// Return if [this] intersects with [other]
   bool intersectsWithQuad(Quad other, {IntersectionResult result}) {
diff --git a/pub/vector_math/lib/src/vector_math/opengl.dart b/pub/vector_math/lib/src/vector_math/opengl.dart
index d46588d..1038ed3 100644
--- a/pub/vector_math/lib/src/vector_math/opengl.dart
+++ b/pub/vector_math/lib/src/vector_math/opengl.dart
@@ -56,10 +56,10 @@
 /// [tx],[ty],[tz] specifies the position of the object.
 void setModelMatrix(Matrix4 modelMatrix, Vector3 forwardDirection,
     Vector3 upDirection, double tx, double ty, double tz) {
-  Vector3 right = forwardDirection.cross(upDirection)..normalize();
-  Vector3 c1 = right;
-  Vector3 c2 = upDirection;
-  Vector3 c3 = -forwardDirection;
+  final Vector3 right = forwardDirection.cross(upDirection)..normalize();
+  final Vector3 c1 = right;
+  final Vector3 c2 = upDirection;
+  final Vector3 c3 = -forwardDirection;
   modelMatrix.setValues(c1[0], c1[1], c1[2], 0.0, c2[0], c2[1], c2[2], 0.0,
       c3[0], c3[1], c3[2], 0.0, tx, ty, tz, 1.0);
 }
@@ -74,16 +74,13 @@
 /// [upDirection] specifies the direction of the up vector (usually, +Y).
 void setViewMatrix(Matrix4 viewMatrix, Vector3 cameraPosition,
     Vector3 cameraFocusPosition, Vector3 upDirection) {
-  Vector3 z = cameraPosition - cameraFocusPosition;
-  z.normalize();
-  Vector3 x = upDirection.cross(z);
-  x.normalize();
-  Vector3 y = z.cross(x);
-  y.normalize();
+  final Vector3 z = (cameraPosition - cameraFocusPosition)..normalize();
+  final Vector3 x = upDirection.cross(z)..normalize();
+  final Vector3 y = z.cross(x)..normalize();
 
-  double rotatedEyeX = -x.dot(cameraPosition);
-  double rotatedEyeY = -y.dot(cameraPosition);
-  double rotatedEyeZ = -z.dot(cameraPosition);
+  final double rotatedEyeX = -x.dot(cameraPosition);
+  final double rotatedEyeY = -y.dot(cameraPosition);
+  final double rotatedEyeZ = -z.dot(cameraPosition);
 
   viewMatrix.setValues(x[0], y[0], z[0], 0.0, x[1], y[1], z[1], 0.0, x[2], y[2],
       z[2], 0.0, rotatedEyeX, rotatedEyeY, rotatedEyeZ, 1.0);
@@ -96,7 +93,7 @@
 /// [upDirection] specifies the direction of the up vector (usually, +Y).
 Matrix4 makeViewMatrix(
     Vector3 cameraPosition, Vector3 cameraFocusPosition, Vector3 upDirection) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setViewMatrix(r, cameraPosition, cameraFocusPosition, upDirection);
   return r;
 }
@@ -113,16 +110,17 @@
 /// (always positive).
 void setPerspectiveMatrix(Matrix4 perspectiveMatrix, double fovYRadians,
     double aspectRatio, double zNear, double zFar) {
-  final double height = Math.tan(fovYRadians * 0.5);
+  final double height = math.tan(fovYRadians * 0.5);
   final double width = height * aspectRatio;
   final double near_minus_far = zNear - zFar;
 
-  final Matrix4 view = perspectiveMatrix..setZero();
-  view.setEntry(0, 0, 1.0 / width);
-  view.setEntry(1, 1, 1.0 / height);
-  view.setEntry(2, 2, (zFar + zNear) / near_minus_far);
-  view.setEntry(3, 2, -1.0);
-  view.setEntry(2, 3, (2.0 * zNear * zFar) / near_minus_far);
+  perspectiveMatrix
+    ..setZero()
+    ..setEntry(0, 0, 1.0 / width)
+    ..setEntry(1, 1, 1.0 / height)
+    ..setEntry(2, 2, (zFar + zNear) / near_minus_far)
+    ..setEntry(3, 2, -1.0)
+    ..setEntry(2, 3, (2.0 * zNear * zFar) / near_minus_far);
 }
 
 /// Constructs a new OpenGL perspective projection matrix.
@@ -137,7 +135,7 @@
 /// (always positive).
 Matrix4 makePerspectiveMatrix(
     double fovYRadians, double aspectRatio, double zNear, double zFar) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setPerspectiveMatrix(r, fovYRadians, aspectRatio, zNear, zFar);
   return r;
 }
@@ -151,15 +149,16 @@
 /// (always positive).
 void setInfiniteMatrix(Matrix4 infiniteMatrix, double fovYRadians,
     double aspectRatio, double zNear) {
-  final double height = Math.tan(fovYRadians * 0.5);
+  final double height = math.tan(fovYRadians * 0.5);
   final double width = height * aspectRatio;
 
-  final Matrix4 view = infiniteMatrix..setZero();
-  view.setEntry(0, 0, 1.0 / width);
-  view.setEntry(1, 1, 1.0 / height);
-  view.setEntry(2, 2, -1.0);
-  view.setEntry(3, 2, -1.0);
-  view.setEntry(2, 3, -2.0 * zNear);
+  infiniteMatrix
+    ..setZero()
+    ..setEntry(0, 0, 1.0 / width)
+    ..setEntry(1, 1, 1.0 / height)
+    ..setEntry(2, 2, -1.0)
+    ..setEntry(3, 2, -1.0)
+    ..setEntry(2, 3, -2.0 * zNear);
 }
 
 /// Constructs a new OpenGL infinite projection matrix.
@@ -172,7 +171,7 @@
 /// (always positive).
 Matrix4 makeInfiniteMatrix(
     double fovYRadians, double aspectRatio, double zNear) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setInfiniteMatrix(r, fovYRadians, aspectRatio, zNear);
   return r;
 }
@@ -187,18 +186,19 @@
 /// planes.
 void setFrustumMatrix(Matrix4 perspectiveMatrix, double left, double right,
     double bottom, double top, double near, double far) {
-  double two_near = 2.0 * near;
-  double right_minus_left = right - left;
-  double top_minus_bottom = top - bottom;
-  double far_minus_near = far - near;
-  Matrix4 view = perspectiveMatrix..setZero();
-  view.setEntry(0, 0, two_near / right_minus_left);
-  view.setEntry(1, 1, two_near / top_minus_bottom);
-  view.setEntry(0, 2, (right + left) / right_minus_left);
-  view.setEntry(1, 2, (top + bottom) / top_minus_bottom);
-  view.setEntry(2, 2, -(far + near) / far_minus_near);
-  view.setEntry(3, 2, -1.0);
-  view.setEntry(2, 3, -(two_near * far) / far_minus_near);
+  final double two_near = 2.0 * near;
+  final double right_minus_left = right - left;
+  final double top_minus_bottom = top - bottom;
+  final double far_minus_near = far - near;
+  perspectiveMatrix
+    ..setZero()
+    ..setEntry(0, 0, two_near / right_minus_left)
+    ..setEntry(1, 1, two_near / top_minus_bottom)
+    ..setEntry(0, 2, (right + left) / right_minus_left)
+    ..setEntry(1, 2, (top + bottom) / top_minus_bottom)
+    ..setEntry(2, 2, -(far + near) / far_minus_near)
+    ..setEntry(3, 2, -1.0)
+    ..setEntry(2, 3, -(two_near * far) / far_minus_near);
 }
 
 /// Constructs a new OpenGL perspective projection matrix.
@@ -211,7 +211,7 @@
 /// planes.
 Matrix4 makeFrustumMatrix(double left, double right, double bottom, double top,
     double near, double far) {
-  Matrix4 view = new Matrix4.zero();
+  final Matrix4 view = new Matrix4.zero();
   setFrustumMatrix(view, left, right, bottom, top, near, far);
   return view;
 }
@@ -226,20 +226,21 @@
 /// planes.
 void setOrthographicMatrix(Matrix4 orthographicMatrix, double left,
     double right, double bottom, double top, double near, double far) {
-  double rml = right - left;
-  double rpl = right + left;
-  double tmb = top - bottom;
-  double tpb = top + bottom;
-  double fmn = far - near;
-  double fpn = far + near;
-  Matrix4 r = orthographicMatrix..setZero();
-  r.setEntry(0, 0, 2.0 / rml);
-  r.setEntry(1, 1, 2.0 / tmb);
-  r.setEntry(2, 2, -2.0 / fmn);
-  r.setEntry(0, 3, -rpl / rml);
-  r.setEntry(1, 3, -tpb / tmb);
-  r.setEntry(2, 3, -fpn / fmn);
-  r.setEntry(3, 3, 1.0);
+  final double rml = right - left;
+  final double rpl = right + left;
+  final double tmb = top - bottom;
+  final double tpb = top + bottom;
+  final double fmn = far - near;
+  final double fpn = far + near;
+  orthographicMatrix
+    ..setZero()
+    ..setEntry(0, 0, 2.0 / rml)
+    ..setEntry(1, 1, 2.0 / tmb)
+    ..setEntry(2, 2, -2.0 / fmn)
+    ..setEntry(0, 3, -rpl / rml)
+    ..setEntry(1, 3, -tpb / tmb)
+    ..setEntry(2, 3, -fpn / fmn)
+    ..setEntry(3, 3, 1.0);
 }
 
 /// Constructs a new OpenGL orthographic projection matrix.
@@ -252,7 +253,7 @@
 /// planes.
 Matrix4 makeOrthographicMatrix(double left, double right, double bottom,
     double top, double near, double far) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setOrthographicMatrix(r, left, right, bottom, top, near, far);
   return r;
 }
@@ -260,14 +261,15 @@
 /// Returns a transformation matrix that transforms points onto
 /// the plane specified with [planeNormal] and [planePoint].
 Matrix4 makePlaneProjection(Vector3 planeNormal, Vector3 planePoint) {
-  Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
+  final Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
       planeNormal.storage[2], 0.0);
-  Matrix4 outer = new Matrix4.outer(v, v);
+  final Matrix4 outer = new Matrix4.outer(v, v);
   Matrix4 r = new Matrix4.zero();
   r = r - outer;
-  Vector3 scaledNormal = (planeNormal.scaled(dot3(planePoint, planeNormal)));
-  Vector4 T = new Vector4(scaledNormal.storage[0], scaledNormal.storage[1],
-      scaledNormal.storage[2], 1.0);
+  final Vector3 scaledNormal =
+      (planeNormal.scaled(dot3(planePoint, planeNormal)));
+  final Vector4 T = new Vector4(scaledNormal.storage[0],
+      scaledNormal.storage[1], scaledNormal.storage[2], 1.0);
   r.setColumn(3, T);
   return r;
 }
@@ -275,16 +277,15 @@
 /// Returns a transformation matrix that transforms points by reflecting
 /// them through the plane specified with [planeNormal] and [planePoint].
 Matrix4 makePlaneReflection(Vector3 planeNormal, Vector3 planePoint) {
-  Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
+  final Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
       planeNormal.storage[2], 0.0);
-  Matrix4 outer = new Matrix4.outer(v, v);
-  outer.scale(2.0);
+  final Matrix4 outer = new Matrix4.outer(v, v)..scale(2.0);
   Matrix4 r = new Matrix4.zero();
   r = r - outer;
-  double scale = 2.0 * planePoint.dot(planeNormal);
-  Vector3 scaledNormal = (planeNormal.scaled(scale));
-  Vector4 T = new Vector4(scaledNormal.storage[0], scaledNormal.storage[1],
-      scaledNormal.storage[2], 1.0);
+  final double scale = 2.0 * planePoint.dot(planeNormal);
+  final Vector3 scaledNormal = (planeNormal.scaled(scale));
+  final Vector4 T = new Vector4(scaledNormal.storage[0],
+      scaledNormal.storage[1], scaledNormal.storage[2], 1.0);
   r.setColumn(3, T);
   return r;
 }
@@ -333,19 +334,21 @@
   }
 
   // Copy camera matrix.
-  Matrix4 invertedCameraMatrix = new Matrix4.copy(cameraMatrix);
+  final Matrix4 invertedCameraMatrix = new Matrix4.copy(cameraMatrix);
   // Invert the camera matrix.
   invertedCameraMatrix.invert();
   // Determine intersection point.
-  Vector4 v = new Vector4(pickX, pickY, pickZ, 1.0);
+  final Vector4 v =
+      new Vector4(pickX.toDouble(), pickY.toDouble(), pickZ.toDouble(), 1.0);
   invertedCameraMatrix.transform(v);
   if (v.w == 0.0) {
     return false;
   }
-  double invW = 1.0 / v.w;
-  pickWorld.x = v.x * invW;
-  pickWorld.y = v.y * invW;
-  pickWorld.z = v.z * invW;
+  final double invW = 1.0 / v.w;
+  pickWorld
+    ..x = v.x * invW
+    ..y = v.y * invW
+    ..z = v.z * invW;
 
   return true;
 }
diff --git a/pub/vector_math/lib/src/vector_math/plane.dart b/pub/vector_math/lib/src/vector_math/plane.dart
index b719ac4..a8b89c9 100644
--- a/pub/vector_math/lib/src/vector_math/plane.dart
+++ b/pub/vector_math/lib/src/vector_math/plane.dart
@@ -11,25 +11,26 @@
   /// Find the intersection point between the three planes [a], [b] and [c] and
   /// copy it into [result].
   static void intersection(Plane a, Plane b, Plane c, Vector3 result) {
-    final cross = new Vector3.zero();
+    final Vector3 cross = new Vector3.zero();
 
     b.normal.crossInto(c.normal, cross);
 
-    final f = -a.normal.dot(cross);
+    final double f = -a.normal.dot(cross);
 
-    final v1 = cross.scaled(a.constant);
+    final Vector3 v1 = cross.scaled(a.constant);
 
     c.normal.crossInto(a.normal, cross);
 
-    final v2 = cross.scaled(b.constant);
+    final Vector3 v2 = cross.scaled(b.constant);
 
     a.normal.crossInto(b.normal, cross);
 
-    final v3 = cross.scaled(c.constant);
+    final Vector3 v3 = cross.scaled(c.constant);
 
-    result.x = (v1.x + v2.x + v3.x) / f;
-    result.y = (v1.y + v2.y + v3.y) / f;
-    result.z = (v1.z + v2.z + v3.z) / f;
+    result
+      ..x = (v1.x + v2.x + v3.x) / f
+      ..y = (v1.y + v2.y + v3.y) / f
+      ..z = (v1.z + v2.z + v3.z) / f;
   }
 
   Vector3 get normal => _normal;
@@ -63,12 +64,10 @@
   }
 
   void normalize() {
-    var inverseLength = 1.0 / normal.length;
+    final double inverseLength = 1.0 / normal.length;
     _normal.scale(inverseLength);
     _constant *= inverseLength;
   }
 
-  double distanceToVector3(Vector3 point) {
-    return _normal.dot(point) + _constant;
-  }
+  double distanceToVector3(Vector3 point) => _normal.dot(point) + _constant;
 }
diff --git a/pub/vector_math/lib/src/vector_math/quad.dart b/pub/vector_math/lib/src/vector_math/quad.dart
index 06442bf..fe78ad4 100644
--- a/pub/vector_math/lib/src/vector_math/quad.dart
+++ b/pub/vector_math/lib/src/vector_math/quad.dart
@@ -54,7 +54,7 @@
 
   /// Copy the normal of [this] into [normal].
   void copyNormalInto(Vector3 normal) {
-    final v0 = _point0.clone()..sub(_point1);
+    final Vector3 v0 = _point0.clone()..sub(_point1);
     normal
       ..setFrom(_point2)
       ..sub(_point1)
@@ -74,10 +74,11 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    t.transform3(_point0);
-    t.transform3(_point1);
-    t.transform3(_point2);
-    t.transform3(_point3);
+    t
+      ..transform3(_point0)
+      ..transform3(_point1)
+      ..transform3(_point2)
+      ..transform3(_point3);
   }
 
   /// Translate [this] by [offset].
diff --git a/pub/vector_math/lib/src/vector_math/quaternion.dart b/pub/vector_math/lib/src/vector_math/quaternion.dart
index 54add8f..0370e11 100644
--- a/pub/vector_math/lib/src/vector_math/quaternion.dart
+++ b/pub/vector_math/lib/src/vector_math/quaternion.dart
@@ -64,7 +64,7 @@
 
   /// Constructs a quaternion with a random rotation. The random number
   /// generator [rn] is used to generate the random numbers for the rotation.
-  factory Quaternion.random(Math.Random rn) =>
+  factory Quaternion.random(math.Random rn) =>
       new Quaternion._()..setRandom(rn);
 
   /// Constructs a quaternion set to the identity quaternion.
@@ -93,7 +93,7 @@
 
   /// Copy [source] into [this].
   void setFrom(Quaternion source) {
-    final sourceStorage = source._qStorage;
+    final Float32List sourceStorage = source._qStorage;
     _qStorage[0] = sourceStorage[0];
     _qStorage[1] = sourceStorage[1];
     _qStorage[2] = sourceStorage[2];
@@ -110,36 +110,36 @@
 
   /// Set the quaternion with rotation of [radians] around [axis].
   void setAxisAngle(Vector3 axis, double radians) {
-    final len = axis.length;
+    final double len = axis.length;
     if (len == 0.0) {
       return;
     }
-    final halfSin = Math.sin(radians * 0.5) / len;
-    final axisStorage = axis.storage;
+    final double halfSin = math.sin(radians * 0.5) / len;
+    final Float32List axisStorage = axis.storage;
     _qStorage[0] = axisStorage[0] * halfSin;
     _qStorage[1] = axisStorage[1] * halfSin;
     _qStorage[2] = axisStorage[2] * halfSin;
-    _qStorage[3] = Math.cos(radians * 0.5);
+    _qStorage[3] = math.cos(radians * 0.5);
   }
 
   /// Set the quaternion with rotation from a rotation matrix [rotationMatrix].
   void setFromRotation(Matrix3 rotationMatrix) {
-    final rotationMatrixStorage = rotationMatrix.storage;
-    final trace = rotationMatrix.trace();
+    final Float32List rotationMatrixStorage = rotationMatrix.storage;
+    final double trace = rotationMatrix.trace();
     if (trace > 0.0) {
-      var s = Math.sqrt(trace + 1.0);
+      double s = math.sqrt(trace + 1.0);
       _qStorage[3] = s * 0.5;
       s = 0.5 / s;
       _qStorage[0] = (rotationMatrixStorage[5] - rotationMatrixStorage[7]) * s;
       _qStorage[1] = (rotationMatrixStorage[6] - rotationMatrixStorage[2]) * s;
       _qStorage[2] = (rotationMatrixStorage[1] - rotationMatrixStorage[3]) * s;
     } else {
-      var i = rotationMatrixStorage[0] < rotationMatrixStorage[4]
+      final int i = rotationMatrixStorage[0] < rotationMatrixStorage[4]
           ? (rotationMatrixStorage[4] < rotationMatrixStorage[8] ? 2 : 1)
           : (rotationMatrixStorage[0] < rotationMatrixStorage[8] ? 2 : 0);
-      var j = (i + 1) % 3;
-      var k = (i + 2) % 3;
-      var s = Math.sqrt(rotationMatrixStorage[rotationMatrix.index(i, i)] -
+      final int j = (i + 1) % 3;
+      final int k = (i + 2) % 3;
+      double s = math.sqrt(rotationMatrixStorage[rotationMatrix.index(i, i)] -
           rotationMatrixStorage[rotationMatrix.index(j, j)] -
           rotationMatrixStorage[rotationMatrix.index(k, k)] +
           1.0);
@@ -158,16 +158,16 @@
   }
 
   void setFromTwoVectors(Vector3 a, Vector3 b) {
-    Vector3 v1 = a.normalized();
-    Vector3 v2 = b.normalized();
+    final Vector3 v1 = a.normalized();
+    final Vector3 v2 = b.normalized();
 
-    double c = v1.dot(v2);
-    double angle = Math.acos(c);
+    final double c = v1.dot(v2);
+    double angle = math.acos(c);
     Vector3 axis = v1.cross(v2);
 
     if ((1.0 + c).abs() < 0.0005) {
       // c \approx -1 indicates 180 degree rotation
-      angle = Math.PI;
+      angle = math.PI;
 
       // a and b are parallel in opposite directions. We need any
       // vector as our rotation axis that is perpendicular.
@@ -190,18 +190,18 @@
 
   /// Set the quaternion to a random rotation. The random number generator [rn]
   /// is used to generate the random numbers for the rotation.
-  void setRandom(Math.Random rn) {
+  void setRandom(math.Random rn) {
     // From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III,
     // pg. 124-132.
-    final x0 = rn.nextDouble();
-    final r1 = Math.sqrt(1.0 - x0);
-    final r2 = Math.sqrt(x0);
-    final t1 = Math.PI * 2.0 * rn.nextDouble();
-    final t2 = Math.PI * 2.0 * rn.nextDouble();
-    final c1 = Math.cos(t1);
-    final s1 = Math.sin(t1);
-    final c2 = Math.cos(t2);
-    final s2 = Math.sin(t2);
+    final double x0 = rn.nextDouble();
+    final double r1 = math.sqrt(1.0 - x0);
+    final double r2 = math.sqrt(x0);
+    final double t1 = math.PI * 2.0 * rn.nextDouble();
+    final double t2 = math.PI * 2.0 * rn.nextDouble();
+    final double c1 = math.cos(t1);
+    final double s1 = math.sin(t1);
+    final double c2 = math.cos(t2);
+    final double s2 = math.sin(t2);
     _qStorage[0] = s1 * r1;
     _qStorage[1] = c1 * r1;
     _qStorage[2] = s2 * r2;
@@ -211,19 +211,19 @@
   /// Set the quaternion to the time derivative of [q] with angular velocity
   /// [omega].
   void setDQ(Quaternion q, Vector3 omega) {
-    final qStorage = q._qStorage;
-    final omegaStorage = omega.storage;
-    final qx = qStorage[0];
-    final qy = qStorage[1];
-    final qz = qStorage[2];
-    final qw = qStorage[3];
-    final ox = omegaStorage[0];
-    final oy = omegaStorage[1];
-    final oz = omegaStorage[2];
-    final _x = ox * qw + oy * qz - oz * qy;
-    final _y = oy * qw + oz * qx - ox * qz;
-    final _z = oz * qw + ox * qy - oy * qx;
-    final _w = -ox * qx - oy * qy - oz * qz;
+    final Float32List qStorage = q._qStorage;
+    final Float32List omegaStorage = omega.storage;
+    final double qx = qStorage[0];
+    final double qy = qStorage[1];
+    final double qz = qStorage[2];
+    final double qw = qStorage[3];
+    final double ox = omegaStorage[0];
+    final double oy = omegaStorage[1];
+    final double oz = omegaStorage[2];
+    final double _x = ox * qw + oy * qz - oz * qy;
+    final double _y = oy * qw + oz * qx - ox * qz;
+    final double _z = oz * qw + ox * qy - oy * qx;
+    final double _w = -ox * qx - oy * qy - oz * qz;
     _qStorage[0] = _x * 0.5;
     _qStorage[1] = _y * 0.5;
     _qStorage[2] = _z * 0.5;
@@ -232,15 +232,15 @@
 
   /// Set quaternion with rotation of [yaw], [pitch] and [roll].
   void setEuler(double yaw, double pitch, double roll) {
-    final halfYaw = yaw * 0.5;
-    final halfPitch = pitch * 0.5;
-    final halfRoll = roll * 0.5;
-    final cosYaw = Math.cos(halfYaw);
-    final sinYaw = Math.sin(halfYaw);
-    final cosPitch = Math.cos(halfPitch);
-    final sinPitch = Math.sin(halfPitch);
-    final cosRoll = Math.cos(halfRoll);
-    final sinRoll = Math.sin(halfRoll);
+    final double halfYaw = yaw * 0.5;
+    final double halfPitch = pitch * 0.5;
+    final double halfRoll = roll * 0.5;
+    final double cosYaw = math.cos(halfYaw);
+    final double sinYaw = math.sin(halfYaw);
+    final double cosPitch = math.cos(halfPitch);
+    final double sinPitch = math.sin(halfPitch);
+    final double cosRoll = math.cos(halfRoll);
+    final double sinRoll = math.sin(halfRoll);
     _qStorage[0] = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
     _qStorage[1] = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
     _qStorage[2] = sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw;
@@ -249,11 +249,11 @@
 
   /// Normalize [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _qStorage[0] *= d;
     _qStorage[1] *= d;
     _qStorage[2] *= d;
@@ -270,7 +270,7 @@
 
   /// Invert [this].
   void inverse() {
-    final l = 1.0 / length2;
+    final double l = 1.0 / length2;
     _qStorage[3] = _qStorage[3] * l;
     _qStorage[2] = -_qStorage[2] * l;
     _qStorage[1] = -_qStorage[1] * l;
@@ -287,36 +287,36 @@
   Quaternion inverted() => clone()..inverse();
 
   /// [radians] of rotation around the [axis] of the rotation.
-  double get radians => 2.0 * Math.acos(_qStorage[3]);
+  double get radians => 2.0 * math.acos(_qStorage[3]);
 
   /// [axis] of rotation.
   Vector3 get axis {
-    final den = 1.0 - (_qStorage[3] * _qStorage[3]);
+    final double den = 1.0 - (_qStorage[3] * _qStorage[3]);
     if (den < 0.0005) {
       // 0-angle rotation, so axis does not matter
       return new Vector3.zero();
     }
 
-    final scale = 1.0 / Math.sqrt(den);
+    final double scale = 1.0 / math.sqrt(den);
     return new Vector3(
         _qStorage[0] * scale, _qStorage[1] * scale, _qStorage[2] * scale);
   }
 
   /// Length squared.
   double get length2 {
-    final x = _qStorage[0];
-    final y = _qStorage[1];
-    final z = _qStorage[2];
-    final w = _qStorage[3];
+    final double x = _qStorage[0];
+    final double y = _qStorage[1];
+    final double z = _qStorage[2];
+    final double w = _qStorage[3];
     return (x * x) + (y * y) + (z * z) + (w * w);
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Returns a copy of [v] rotated by quaternion.
   Vector3 rotated(Vector3 v) {
-    final out = v.clone();
+    final Vector3 out = v.clone();
     rotate(out);
     return out;
   }
@@ -324,22 +324,22 @@
   /// Rotates [v] by [this].
   Vector3 rotate(Vector3 v) {
     // conjugate(this) * [v,0] * this
-    final _w = _qStorage[3];
-    final _z = _qStorage[2];
-    final _y = _qStorage[1];
-    final _x = _qStorage[0];
-    final tiw = _w;
-    final tiz = -_z;
-    final tiy = -_y;
-    final tix = -_x;
-    final tx = tiw * v.x + tix * 0.0 + tiy * v.z - tiz * v.y;
-    final ty = tiw * v.y + tiy * 0.0 + tiz * v.x - tix * v.z;
-    final tz = tiw * v.z + tiz * 0.0 + tix * v.y - tiy * v.x;
-    final tw = tiw * 0.0 - tix * v.x - tiy * v.y - tiz * v.z;
-    final result_x = tw * _x + tx * _w + ty * _z - tz * _y;
-    final result_y = tw * _y + ty * _w + tz * _x - tx * _z;
-    final result_z = tw * _z + tz * _w + tx * _y - ty * _x;
-    final vStorage = v.storage;
+    final double _w = _qStorage[3];
+    final double _z = _qStorage[2];
+    final double _y = _qStorage[1];
+    final double _x = _qStorage[0];
+    final double tiw = _w;
+    final double tiz = -_z;
+    final double tiy = -_y;
+    final double tix = -_x;
+    final double tx = tiw * v.x + tix * 0.0 + tiy * v.z - tiz * v.y;
+    final double ty = tiw * v.y + tiy * 0.0 + tiz * v.x - tix * v.z;
+    final double tz = tiw * v.z + tiz * 0.0 + tix * v.y - tiy * v.x;
+    final double tw = tiw * 0.0 - tix * v.x - tiy * v.y - tiz * v.z;
+    final double result_x = tw * _x + tx * _w + ty * _z - tz * _y;
+    final double result_y = tw * _y + ty * _w + tz * _x - tx * _z;
+    final double result_z = tw * _z + tz * _w + tx * _y - ty * _x;
+    final Float32List vStorage = v.storage;
     vStorage[2] = result_z;
     vStorage[1] = result_y;
     vStorage[0] = result_x;
@@ -348,7 +348,7 @@
 
   /// Add [arg] to [this].
   void add(Quaternion arg) {
-    final argStorage = arg._qStorage;
+    final Float32List argStorage = arg._qStorage;
     _qStorage[0] = _qStorage[0] + argStorage[0];
     _qStorage[1] = _qStorage[1] + argStorage[1];
     _qStorage[2] = _qStorage[2] + argStorage[2];
@@ -357,7 +357,7 @@
 
   /// Subtracts [arg] from [this].
   void sub(Quaternion arg) {
-    final argStorage = arg._qStorage;
+    final Float32List argStorage = arg._qStorage;
     _qStorage[0] = _qStorage[0] - argStorage[0];
     _qStorage[1] = _qStorage[1] - argStorage[1];
     _qStorage[2] = _qStorage[2] - argStorage[2];
@@ -377,15 +377,15 @@
 
   /// [this] rotated by [other].
   Quaternion operator *(Quaternion other) {
-    double _w = _qStorage[3];
-    double _z = _qStorage[2];
-    double _y = _qStorage[1];
-    double _x = _qStorage[0];
-    final otherStorage = other._qStorage;
-    double ow = otherStorage[3];
-    double oz = otherStorage[2];
-    double oy = otherStorage[1];
-    double ox = otherStorage[0];
+    final double _w = _qStorage[3];
+    final double _z = _qStorage[2];
+    final double _y = _qStorage[1];
+    final double _x = _qStorage[0];
+    final Float32List otherStorage = other._qStorage;
+    final double ow = otherStorage[3];
+    final double oz = otherStorage[2];
+    final double oy = otherStorage[1];
+    final double ox = otherStorage[0];
     return new Quaternion(
         _w * ox + _x * ow + _y * oz - _z * oy,
         _w * oy + _y * ow + _z * ox - _x * oz,
@@ -416,32 +416,32 @@
   /// Set [rotationMatrix] to a rotation matrix containing the same rotation as
   /// [this].
   Matrix3 copyRotationInto(Matrix3 rotationMatrix) {
-    final d = length2;
+    final double d = length2;
     assert(d != 0.0);
-    final s = 2.0 / d;
+    final double s = 2.0 / d;
 
-    final _x = _qStorage[0];
-    final _y = _qStorage[1];
-    final _z = _qStorage[2];
-    final _w = _qStorage[3];
+    final double _x = _qStorage[0];
+    final double _y = _qStorage[1];
+    final double _z = _qStorage[2];
+    final double _w = _qStorage[3];
 
-    final xs = _x * s;
-    final ys = _y * s;
-    final zs = _z * s;
+    final double xs = _x * s;
+    final double ys = _y * s;
+    final double zs = _z * s;
 
-    final wx = _w * xs;
-    final wy = _w * ys;
-    final wz = _w * zs;
+    final double wx = _w * xs;
+    final double wy = _w * ys;
+    final double wz = _w * zs;
 
-    final xx = _x * xs;
-    final xy = _x * ys;
-    final xz = _x * zs;
+    final double xx = _x * xs;
+    final double xy = _x * ys;
+    final double xz = _x * zs;
 
-    final yy = _y * ys;
-    final yz = _y * zs;
-    final zz = _z * zs;
+    final double yy = _y * ys;
+    final double yz = _y * zs;
+    final double zz = _z * zs;
 
-    final rotationMatrixStorage = rotationMatrix.storage;
+    final Float32List rotationMatrixStorage = rotationMatrix.storage;
     rotationMatrixStorage[0] = 1.0 - (yy + zz); // column 0
     rotationMatrixStorage[1] = xy + wz;
     rotationMatrixStorage[2] = xz - wy;
@@ -455,22 +455,23 @@
   }
 
   /// Printable string.
+  @override
   String toString() => '${_qStorage[0]}, ${_qStorage[1]},'
       ' ${_qStorage[2]} @ ${_qStorage[3]}';
 
   /// Relative error between [this] and [correct].
   double relativeError(Quaternion correct) {
-    final diff = correct - this;
-    final norm_diff = diff.length;
-    final correct_norm = correct.length;
+    final Quaternion diff = correct - this;
+    final double norm_diff = diff.length;
+    final double correct_norm = correct.length;
     return norm_diff / correct_norm;
   }
 
   /// Absolute error between [this] and [correct].
   double absoluteError(Quaternion correct) {
-    final this_norm = length;
-    final correct_norm = correct.length;
-    final norm_diff = (this_norm - correct_norm).abs();
+    final double this_norm = length;
+    final double correct_norm = correct.length;
+    final double norm_diff = (this_norm - correct_norm).abs();
     return norm_diff;
   }
 }
diff --git a/pub/vector_math/lib/src/vector_math/ray.dart b/pub/vector_math/lib/src/vector_math/ray.dart
index a2ca3cc..60efc11 100644
--- a/pub/vector_math/lib/src/vector_math/ray.dart
+++ b/pub/vector_math/lib/src/vector_math/ray.dart
@@ -51,19 +51,19 @@
   /// Return the distance from the origin of [this] to the intersection with
   /// [other] if [this] intersects with [other], or null if the don't intersect.
   double intersectsWithSphere(Sphere other) {
-    final r = other._radius;
-    final r2 = r * r;
-    final l = other._center.clone()..sub(_origin);
-    final s = l.dot(_direction);
-    final l2 = l.dot(l);
+    final double r = other._radius;
+    final double r2 = r * r;
+    final Vector3 l = other._center.clone()..sub(_origin);
+    final double s = l.dot(_direction);
+    final double l2 = l.dot(l);
     if (s < 0 && l2 > r2) {
       return null;
     }
-    final m2 = l2 - s * s;
+    final double m2 = l2 - s * s;
     if (m2 > r2) {
       return null;
     }
-    final q = Math.sqrt(r2 - m2);
+    final double q = math.sqrt(r2 - m2);
 
     return (l2 > r2) ? s - q : s + q;
   }
@@ -71,20 +71,20 @@
   // Some varaibles that are used for intersectsWithTriangle and
   // intersectsWithQuad. The performance is better in Dart and JS if we avoid
   // to create temporary instance over and over. Also reduce GC.
-  static final _e1 = new Vector3.zero();
-  static final _e2 = new Vector3.zero();
-  static final _q = new Vector3.zero();
-  static final _s = new Vector3.zero();
-  static final _r = new Vector3.zero();
+  static final Vector3 _e1 = new Vector3.zero();
+  static final Vector3 _e2 = new Vector3.zero();
+  static final Vector3 _q = new Vector3.zero();
+  static final Vector3 _s = new Vector3.zero();
+  static final Vector3 _r = new Vector3.zero();
 
   /// Return the distance from the origin of [this] to the intersection with
   /// [other] if [this] intersects with [other], or null if the don't intersect.
   double intersectsWithTriangle(Triangle other) {
     const double EPSILON = 10e-6;
 
-    final point0 = other._point0;
-    final point1 = other._point1;
-    final point2 = other._point2;
+    final Vector3 point0 = other._point0;
+    final Vector3 point1 = other._point1;
+    final Vector3 point2 = other._point2;
 
     _e1
       ..setFrom(point1)
@@ -94,30 +94,30 @@
       ..sub(point0);
 
     _direction.crossInto(_e2, _q);
-    final a = _e1.dot(_q);
+    final double a = _e1.dot(_q);
 
     if (a > -EPSILON && a < EPSILON) {
       return null;
     }
 
-    final f = 1 / a;
+    final double f = 1 / a;
     _s
       ..setFrom(_origin)
       ..sub(point0);
-    final u = f * (_s.dot(_q));
+    final double u = f * (_s.dot(_q));
 
     if (u < 0.0) {
       return null;
     }
 
     _s.crossInto(_e1, _r);
-    final v = f * (_direction.dot(_r));
+    final double v = f * (_direction.dot(_r));
 
     if (v < -EPSILON || u + v > 1.0 + EPSILON) {
       return null;
     }
 
-    final t = f * (_e2.dot(_r));
+    final double t = f * (_e2.dot(_r));
 
     return t;
   }
@@ -128,9 +128,9 @@
     const double EPSILON = 10e-6;
 
     // First triangle
-    var point0 = other._point0;
-    var point1 = other._point1;
-    var point2 = other._point2;
+    Vector3 point0 = other._point0;
+    Vector3 point1 = other._point1;
+    Vector3 point2 = other._point2;
 
     _e1
       ..setFrom(point1)
@@ -140,21 +140,21 @@
       ..sub(point0);
 
     _direction.crossInto(_e2, _q);
-    final a0 = _e1.dot(_q);
+    final double a0 = _e1.dot(_q);
 
     if (!(a0 > -EPSILON && a0 < EPSILON)) {
-      final f = 1 / a0;
+      final double f = 1 / a0;
       _s
         ..setFrom(_origin)
         ..sub(point0);
-      final u = f * (_s.dot(_q));
+      final double u = f * (_s.dot(_q));
 
       if (u >= 0.0) {
         _s.crossInto(_e1, _r);
-        final v = f * (_direction.dot(_r));
+        final double v = f * (_direction.dot(_r));
 
         if (!(v < -EPSILON || u + v > 1.0 + EPSILON)) {
-          final t = f * (_e2.dot(_r));
+          final double t = f * (_e2.dot(_r));
 
           return t;
         }
@@ -174,21 +174,21 @@
       ..sub(point0);
 
     _direction.crossInto(_e2, _q);
-    final a1 = _e1.dot(_q);
+    final double a1 = _e1.dot(_q);
 
     if (!(a1 > -EPSILON && a1 < EPSILON)) {
-      final f = 1 / a1;
+      final double f = 1 / a1;
       _s
         ..setFrom(_origin)
         ..sub(point0);
-      final u = f * (_s.dot(_q));
+      final double u = f * (_s.dot(_q));
 
       if (u >= 0.0) {
         _s.crossInto(_e1, _r);
-        final v = f * (_direction.dot(_r));
+        final double v = f * (_direction.dot(_r));
 
         if (!(v < -EPSILON || u + v > 1.0 + EPSILON)) {
-          final t = f * (_e2.dot(_r));
+          final double t = f * (_e2.dot(_r));
 
           return t;
         }
@@ -201,23 +201,23 @@
   /// Return the distance from the origin of [this] to the intersection with
   /// [other] if [this] intersects with [other], or null if the don't intersect.
   double intersectsWithAabb3(Aabb3 other) {
-    final otherMin = other.min;
-    final otherMax = other.max;
+    final Vector3 otherMin = other.min;
+    final Vector3 otherMax = other.max;
 
-    var tNear = -double.MAX_FINITE;
-    var tFar = double.MAX_FINITE;
+    double tNear = -double.MAX_FINITE;
+    double tFar = double.MAX_FINITE;
 
-    for (var i = 0; i < 3; ++i) {
+    for (int i = 0; i < 3; ++i) {
       if (_direction[i] == 0.0) {
         if (_origin[i] < otherMin[i] || _origin[i] > otherMax[i]) {
           return null;
         }
       } else {
-        var t1 = (otherMin[i] - _origin[i]) / _direction[i];
-        var t2 = (otherMax[i] - _origin[i]) / _direction[i];
+        double t1 = (otherMin[i] - _origin[i]) / _direction[i];
+        double t2 = (otherMax[i] - _origin[i]) / _direction[i];
 
         if (t1 > t2) {
-          final temp = t1;
+          final double temp = t1;
           t1 = t2;
           t2 = temp;
         }
diff --git a/pub/vector_math/lib/src/vector_math/sphere.dart b/pub/vector_math/lib/src/vector_math/sphere.dart
index d645287..0e9716d 100644
--- a/pub/vector_math/lib/src/vector_math/sphere.dart
+++ b/pub/vector_math/lib/src/vector_math/sphere.dart
@@ -38,18 +38,16 @@
   }
 
   /// Return if [this] contains [other].
-  bool containsVector3(Vector3 other) {
-    return other.distanceToSquared(center) < radius * radius;
-  }
+  bool containsVector3(Vector3 other) =>
+      other.distanceToSquared(center) < radius * radius;
 
   /// Return if [this] intersects with [other].
-  bool intersectsWithVector3(Vector3 other) {
-    return other.distanceToSquared(center) <= radius * radius;
-  }
+  bool intersectsWithVector3(Vector3 other) =>
+      other.distanceToSquared(center) <= radius * radius;
 
   /// Return if [this] intersects with [other].
   bool intersectsWithSphere(Sphere other) {
-    var radiusSum = radius + other.radius;
+    final double radiusSum = radius + other.radius;
 
     return other.center.distanceToSquared(center) <= (radiusSum * radiusSum);
   }
diff --git a/pub/vector_math/lib/src/vector_math/third_party/noise.dart b/pub/vector_math/lib/src/vector_math/third_party/noise.dart
index 0e695ba..a20aa40 100644
--- a/pub/vector_math/lib/src/vector_math/third_party/noise.dart
+++ b/pub/vector_math/lib/src/vector_math/third_party/noise.dart
@@ -27,54 +27,54 @@
  */
 
 class SimplexNoise {
-  static final _grad3 = <List<double>>[
-    [1.0, 1.0, 0.0],
-    [-1.0, 1.0, 0.0],
-    [1.0, -1.0, 0.0],
-    [-1.0, -1.0, 0.0],
-    [1.0, 0.0, 1.0],
-    [-1.0, 0.0, 1.0],
-    [1.0, 0.0, -1.0],
-    [-1.0, 0.0, -1.0],
-    [0.0, 1.0, 1.0],
-    [0.0, -1.0, 1.0],
-    [0.0, 1.0, -1.0],
-    [0.0, -1.0, -1.0]
+  static final List<List<double>> _grad3 = <List<double>>[
+    <double>[1.0, 1.0, 0.0],
+    <double>[-1.0, 1.0, 0.0],
+    <double>[1.0, -1.0, 0.0],
+    <double>[-1.0, -1.0, 0.0],
+    <double>[1.0, 0.0, 1.0],
+    <double>[-1.0, 0.0, 1.0],
+    <double>[1.0, 0.0, -1.0],
+    <double>[-1.0, 0.0, -1.0],
+    <double>[0.0, 1.0, 1.0],
+    <double>[0.0, -1.0, 1.0],
+    <double>[0.0, 1.0, -1.0],
+    <double>[0.0, -1.0, -1.0]
   ];
 
-  static final _grad4 = <List<double>>[
-    [0.0, 1.0, 1.0, 1.0],
-    [0.0, 1.0, 1.0, -1.0],
-    [0.0, 1.0, -1.0, 1.0],
-    [0.0, 1.0, -1.0, -1.0],
-    [0.0, -1.0, 1.0, 1.0],
-    [0.0, -1.0, 1.0, -1.0],
-    [0.0, -1.0, -1.0, 1.0],
-    [0.0, -1.0, -1.0, -1.0],
-    [1.0, 0.0, 1.0, 1.0],
-    [1.0, 0.0, 1.0, -1.0],
-    [1.0, 0.0, -1.0, 1.0],
-    [1.0, 0.0, -1.0, -1.0],
-    [-1.0, 0.0, 1.0, 1.0],
-    [-1.0, 0.0, 1.0, -1.0],
-    [-1.0, 0.0, -1.0, 1.0],
-    [-1.0, 0.0, -1.0, -1.0],
-    [1.0, 1.0, 0.0, 1.0],
-    [1.0, 1.0, 0.0, -1.0],
-    [1.0, -1.0, 0.0, 1.0],
-    [1.0, -1.0, 0.0, -1.0],
-    [-1.0, 1.0, 0.0, 1.0],
-    [-1.0, 1.0, 0.0, -1.0],
-    [-1.0, -1.0, 0.0, 1.0],
-    [-1.0, -1.0, 0.0, -1.0],
-    [1.0, 1.0, 1.0, 0.0],
-    [1.0, 1.0, -1.0, 0.0],
-    [1.0, -1.0, 1.0, 0.0],
-    [1.0, -1.0, -1.0, 0.0],
-    [-1.0, 1.0, 1.0, 0.0],
-    [-1.0, 1.0, -1.0, 0.0],
-    [-1.0, -1.0, 1.0, 0.0],
-    [-1.0, -1.0, -1.0, 0.0]
+  static final List<List<double>> _grad4 = <List<double>>[
+    <double>[0.0, 1.0, 1.0, 1.0],
+    <double>[0.0, 1.0, 1.0, -1.0],
+    <double>[0.0, 1.0, -1.0, 1.0],
+    <double>[0.0, 1.0, -1.0, -1.0],
+    <double>[0.0, -1.0, 1.0, 1.0],
+    <double>[0.0, -1.0, 1.0, -1.0],
+    <double>[0.0, -1.0, -1.0, 1.0],
+    <double>[0.0, -1.0, -1.0, -1.0],
+    <double>[1.0, 0.0, 1.0, 1.0],
+    <double>[1.0, 0.0, 1.0, -1.0],
+    <double>[1.0, 0.0, -1.0, 1.0],
+    <double>[1.0, 0.0, -1.0, -1.0],
+    <double>[-1.0, 0.0, 1.0, 1.0],
+    <double>[-1.0, 0.0, 1.0, -1.0],
+    <double>[-1.0, 0.0, -1.0, 1.0],
+    <double>[-1.0, 0.0, -1.0, -1.0],
+    <double>[1.0, 1.0, 0.0, 1.0],
+    <double>[1.0, 1.0, 0.0, -1.0],
+    <double>[1.0, -1.0, 0.0, 1.0],
+    <double>[1.0, -1.0, 0.0, -1.0],
+    <double>[-1.0, 1.0, 0.0, 1.0],
+    <double>[-1.0, 1.0, 0.0, -1.0],
+    <double>[-1.0, -1.0, 0.0, 1.0],
+    <double>[-1.0, -1.0, 0.0, -1.0],
+    <double>[1.0, 1.0, 1.0, 0.0],
+    <double>[1.0, 1.0, -1.0, 0.0],
+    <double>[1.0, -1.0, 1.0, 0.0],
+    <double>[1.0, -1.0, -1.0, 0.0],
+    <double>[-1.0, 1.0, 1.0, 0.0],
+    <double>[-1.0, 1.0, -1.0, 0.0],
+    <double>[-1.0, -1.0, 1.0, 0.0],
+    <double>[-1.0, -1.0, -1.0, 0.0]
   ];
 
   // To remove the need for index wrapping, double the permutation table length
@@ -82,12 +82,12 @@
   List<int> _permMod12;
 
   // Skewing and unskewing factors for 2, 3, and 4 dimensions
-  static final double _F2 = 0.5 * (Math.sqrt(3.0) - 1.0);
-  static final double _G2 = (3.0 - Math.sqrt(3.0)) / 6.0;
+  static final double _F2 = 0.5 * (math.sqrt(3.0) - 1.0);
+  static final double _G2 = (3.0 - math.sqrt(3.0)) / 6.0;
   static const double _F3 = 1.0 / 3.0;
   static const double _G3 = 1.0 / 6.0;
-  static final double _F4 = (Math.sqrt(5.0) - 1.0) / 4.0;
-  static final double _G4 = (5.0 - Math.sqrt(5.0)) / 20.0;
+  static final double _F4 = (math.sqrt(5.0) - 1.0) / 4.0;
+  static final double _G4 = (5.0 - math.sqrt(5.0)) / 20.0;
 
   double _dot2(List<double> g, double x, double y) => g[0] * x + g[1] * y;
 
@@ -97,29 +97,27 @@
   double _dot4(List<double> g, double x, double y, double z, double w) =>
       g[0] * x + g[1] * y + g[2] * z + g[3] * w;
 
-  SimplexNoise([Math.Random r]) {
-    if (r == null) {
-      r = new Math.Random();
-    }
-    List<int> p =
-        new List<int>.generate(256, (i) => r.nextInt(256), growable: false);
-    _perm = new List<int>.generate(p.length * 2, (i) => p[i % p.length],
+  SimplexNoise([math.Random r]) {
+    r ??= new math.Random();
+    final List<int> p =
+        new List<int>.generate(256, (_) => r.nextInt(256), growable: false);
+    _perm = new List<int>.generate(p.length * 2, (int i) => p[i % p.length],
         growable: false);
-    _permMod12 = new List<int>.generate(_perm.length, (i) => _perm[i] % 12,
+    _permMod12 = new List<int>.generate(_perm.length, (int i) => _perm[i] % 12,
         growable: false);
   }
 
   double noise2D(double xin, double yin) {
     double n0, n1, n2; // Noise contributions from the three corners
     // Skew the input space to determine which simplex cell we're in
-    double s = (xin + yin) * _F2; // Hairy factor for 2D
-    int i = (xin + s).floor();
-    int j = (yin + s).floor();
-    double t = (i + j) * _G2;
-    double X0 = i - t; // Unskew the cell origin back to (x,y) space
-    double Y0 = j - t;
-    double x0 = xin - X0; // The x,y distances from the cell origin
-    double y0 = yin - Y0;
+    final double s = (xin + yin) * _F2; // Hairy factor for 2D
+    final int i = (xin + s).floor();
+    final int j = (yin + s).floor();
+    final double t = (i + j) * _G2;
+    final double X0 = i - t; // Unskew the cell origin back to (x,y) space
+    final double Y0 = j - t;
+    final double x0 = xin - X0; // The x,y distances from the cell origin
+    final double y0 = yin - Y0;
     // For the 2D case, the simplex shape is an equilateral triangle.
     // Determine which simplex we are in.
     int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
@@ -134,19 +132,19 @@
     // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
     // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
     // c = (3-sqrt(3))/6
-    double x1 =
+    final double x1 =
         x0 - i1 + _G2; // Offsets for middle corner in (x,y) unskewed coords
-    double y1 = y0 - j1 + _G2;
-    double x2 = x0 -
+    final double y1 = y0 - j1 + _G2;
+    final double x2 = x0 -
         1.0 +
         2.0 * _G2; // Offsets for last corner in (x,y) unskewed coords
-    double y2 = y0 - 1.0 + 2.0 * _G2;
+    final double y2 = y0 - 1.0 + 2.0 * _G2;
     // Work out the hashed gradient indices of the three simplex corners
-    int ii = i & 255;
-    int jj = j & 255;
-    int gi0 = _permMod12[ii + _perm[jj]];
-    int gi1 = _permMod12[ii + i1 + _perm[jj + j1]];
-    int gi2 = _permMod12[ii + 1 + _perm[jj + 1]];
+    final int ii = i & 255;
+    final int jj = j & 255;
+    final int gi0 = _permMod12[ii + _perm[jj]];
+    final int gi1 = _permMod12[ii + i1 + _perm[jj + j1]];
+    final int gi2 = _permMod12[ii + 1 + _perm[jj + 1]];
     // Calculate the contribution from the three corners
     double t0 = 0.5 - x0 * x0 - y0 * y0;
     if (t0 < 0)
@@ -180,18 +178,18 @@
   double noise3D(double xin, double yin, double zin) {
     double n0, n1, n2, n3; // Noise contributions from the four corners
     // Skew the input space to determine which simplex cell we're in
-    double s =
+    final double s =
         (xin + yin + zin) * _F3; // Very nice and simple skew factor for 3D
-    int i = (xin + s).floor();
-    int j = (yin + s).floor();
-    int k = (zin + s).floor();
-    double t = (i + j + k) * _G3;
-    double X0 = i - t; // Unskew the cell origin back to (x,y,z) space
-    double Y0 = j - t;
-    double Z0 = k - t;
-    double x0 = xin - X0; // The x,y,z distances from the cell origin
-    double y0 = yin - Y0;
-    double z0 = zin - Z0;
+    final int i = (xin + s).floor();
+    final int j = (yin + s).floor();
+    final int k = (zin + s).floor();
+    final double t = (i + j + k) * _G3;
+    final double X0 = i - t; // Unskew the cell origin back to (x,y,z) space
+    final double Y0 = j - t;
+    final double Z0 = k - t;
+    final double x0 = xin - X0; // The x,y,z distances from the cell origin
+    final double y0 = yin - Y0;
+    final double z0 = zin - Z0;
     // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
     // Determine which simplex we are in.
     int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
@@ -252,25 +250,26 @@
     // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
     // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
     // c = 1/6.
-    double x1 = x0 - i1 + _G3; // Offsets for second corner in (x,y,z) coords
-    double y1 = y0 - j1 + _G3;
-    double z1 = z0 - k1 + _G3;
-    double x2 =
+    final double x1 =
+        x0 - i1 + _G3; // Offsets for second corner in (x,y,z) coords
+    final double y1 = y0 - j1 + _G3;
+    final double z1 = z0 - k1 + _G3;
+    final double x2 =
         x0 - i2 + 2.0 * _G3; // Offsets for third corner in (x,y,z) coords
-    double y2 = y0 - j2 + 2.0 * _G3;
-    double z2 = z0 - k2 + 2.0 * _G3;
-    double x3 =
+    final double y2 = y0 - j2 + 2.0 * _G3;
+    final double z2 = z0 - k2 + 2.0 * _G3;
+    final double x3 =
         x0 - 1.0 + 3.0 * _G3; // Offsets for last corner in (x,y,z) coords
-    double y3 = y0 - 1.0 + 3.0 * _G3;
-    double z3 = z0 - 1.0 + 3.0 * _G3;
+    final double y3 = y0 - 1.0 + 3.0 * _G3;
+    final double z3 = z0 - 1.0 + 3.0 * _G3;
     // Work out the hashed gradient indices of the four simplex corners
-    int ii = i & 255;
-    int jj = j & 255;
-    int kk = k & 255;
-    int gi0 = _permMod12[ii + _perm[jj + _perm[kk]]];
-    int gi1 = _permMod12[ii + i1 + _perm[jj + j1 + _perm[kk + k1]]];
-    int gi2 = _permMod12[ii + i2 + _perm[jj + j2 + _perm[kk + k2]]];
-    int gi3 = _permMod12[ii + 1 + _perm[jj + 1 + _perm[kk + 1]]];
+    final int ii = i & 255;
+    final int jj = j & 255;
+    final int kk = k & 255;
+    final int gi0 = _permMod12[ii + _perm[jj + _perm[kk]]];
+    final int gi1 = _permMod12[ii + i1 + _perm[jj + j1 + _perm[kk + k1]]];
+    final int gi2 = _permMod12[ii + i2 + _perm[jj + j2 + _perm[kk + k2]]];
+    final int gi3 = _permMod12[ii + 1 + _perm[jj + 1 + _perm[kk + 1]]];
     // Calculate the contribution from the four corners
     double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
     if (t0 < 0)
@@ -309,20 +308,20 @@
   double noise4D(double x, double y, double z, double w) {
     double n0, n1, n2, n3, n4; // Noise contributions from the five corners
     // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
-    double s = (x + y + z + w) * _F4; // Factor for 4D skewing
-    int i = (x + s).floor();
-    int j = (y + s).floor();
-    int k = (z + s).floor();
-    int l = (w + s).floor();
-    double t = (i + j + k + l) * _G4; // Factor for 4D unskewing
-    double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
-    double Y0 = j - t;
-    double Z0 = k - t;
-    double W0 = l - t;
-    double x0 = x - X0; // The x,y,z,w distances from the cell origin
-    double y0 = y - Y0;
-    double z0 = z - Z0;
-    double w0 = w - W0;
+    final double s = (x + y + z + w) * _F4; // Factor for 4D skewing
+    final int i = (x + s).floor();
+    final int j = (y + s).floor();
+    final int k = (z + s).floor();
+    final int l = (w + s).floor();
+    final double t = (i + j + k + l) * _G4; // Factor for 4D unskewing
+    final double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
+    final double Y0 = j - t;
+    final double Z0 = k - t;
+    final double W0 = l - t;
+    final double x0 = x - X0; // The x,y,z,w distances from the cell origin
+    final double y0 = y - Y0;
+    final double z0 = z - Z0;
+    final double w0 = w - W0;
     // For the 4D case, the simplex is a 4D shape I won't even try to describe.
     // To find out which of the 24 possible simplices we're in, we need to
     // determine the magnitude ordering of x0, y0, z0 and w0.
@@ -379,38 +378,39 @@
     k3 = rankz >= 1 ? 1 : 0;
     l3 = rankw >= 1 ? 1 : 0;
     // The fifth corner has all coordinate offsets = 1, so no need to compute that.
-    double x1 = x0 - i1 + _G4; // Offsets for second corner in (x,y,z,w) coords
-    double y1 = y0 - j1 + _G4;
-    double z1 = z0 - k1 + _G4;
-    double w1 = w0 - l1 + _G4;
-    double x2 =
+    final double x1 =
+        x0 - i1 + _G4; // Offsets for second corner in (x,y,z,w) coords
+    final double y1 = y0 - j1 + _G4;
+    final double z1 = z0 - k1 + _G4;
+    final double w1 = w0 - l1 + _G4;
+    final double x2 =
         x0 - i2 + 2.0 * _G4; // Offsets for third corner in (x,y,z,w) coords
-    double y2 = y0 - j2 + 2.0 * _G4;
-    double z2 = z0 - k2 + 2.0 * _G4;
-    double w2 = w0 - l2 + 2.0 * _G4;
-    double x3 =
+    final double y2 = y0 - j2 + 2.0 * _G4;
+    final double z2 = z0 - k2 + 2.0 * _G4;
+    final double w2 = w0 - l2 + 2.0 * _G4;
+    final double x3 =
         x0 - i3 + 3.0 * _G4; // Offsets for fourth corner in (x,y,z,w) coords
-    double y3 = y0 - j3 + 3.0 * _G4;
-    double z3 = z0 - k3 + 3.0 * _G4;
-    double w3 = w0 - l3 + 3.0 * _G4;
-    double x4 =
+    final double y3 = y0 - j3 + 3.0 * _G4;
+    final double z3 = z0 - k3 + 3.0 * _G4;
+    final double w3 = w0 - l3 + 3.0 * _G4;
+    final double x4 =
         x0 - 1.0 + 4.0 * _G4; // Offsets for last corner in (x,y,z,w) coords
-    double y4 = y0 - 1.0 + 4.0 * _G4;
-    double z4 = z0 - 1.0 + 4.0 * _G4;
-    double w4 = w0 - 1.0 + 4.0 * _G4;
+    final double y4 = y0 - 1.0 + 4.0 * _G4;
+    final double z4 = z0 - 1.0 + 4.0 * _G4;
+    final double w4 = w0 - 1.0 + 4.0 * _G4;
     // Work out the hashed gradient indices of the five simplex corners
-    int ii = i & 255;
-    int jj = j & 255;
-    int kk = k & 255;
-    int ll = l & 255;
-    int gi0 = _perm[ii + _perm[jj + _perm[kk + _perm[ll]]]] % 32;
-    int gi1 =
+    final int ii = i & 255;
+    final int jj = j & 255;
+    final int kk = k & 255;
+    final int ll = l & 255;
+    final int gi0 = _perm[ii + _perm[jj + _perm[kk + _perm[ll]]]] % 32;
+    final int gi1 =
         _perm[ii + i1 + _perm[jj + j1 + _perm[kk + k1 + _perm[ll + l1]]]] % 32;
-    int gi2 =
+    final int gi2 =
         _perm[ii + i2 + _perm[jj + j2 + _perm[kk + k2 + _perm[ll + l2]]]] % 32;
-    int gi3 =
+    final int gi3 =
         _perm[ii + i3 + _perm[jj + j3 + _perm[kk + k3 + _perm[ll + l3]]]] % 32;
-    int gi4 =
+    final int gi4 =
         _perm[ii + 1 + _perm[jj + 1 + _perm[kk + 1 + _perm[ll + 1]]]] % 32;
     // Calculate the contribution from the five corners
     double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
diff --git a/pub/vector_math/lib/src/vector_math/triangle.dart b/pub/vector_math/lib/src/vector_math/triangle.dart
index c1cf53d..fb486a6 100644
--- a/pub/vector_math/lib/src/vector_math/triangle.dart
+++ b/pub/vector_math/lib/src/vector_math/triangle.dart
@@ -46,7 +46,7 @@
 
   /// Copy the normal of [this] into [normal].
   void copyNormalInto(Vector3 normal) {
-    final v0 = point0.clone()..sub(point1);
+    final Vector3 v0 = point0.clone()..sub(point1);
     normal
       ..setFrom(point2)
       ..sub(point1)
@@ -56,9 +56,7 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    t.transform3(_point0);
-    t.transform3(_point1);
-    t.transform3(_point2);
+    t..transform3(_point0)..transform3(_point1)..transform3(_point2);
   }
 
   /// Translate [this] by [offset].
diff --git a/pub/vector_math/lib/src/vector_math/utilities.dart b/pub/vector_math/lib/src/vector_math/utilities.dart
index d48ea42..29cc2a2 100644
--- a/pub/vector_math/lib/src/vector_math/utilities.dart
+++ b/pub/vector_math/lib/src/vector_math/utilities.dart
@@ -5,39 +5,32 @@
 part of vector_math;
 
 /// Convert [radians] to degrees.
-double degrees(double radians) {
-  return radians * radians2Degrees;
-}
+double degrees(double radians) => radians * radians2Degrees;
 
 /// Convert [degrees] to radians.
-double radians(double degrees) {
-  return degrees * degrees2Radians;
-}
+double radians(double degrees) => degrees * degrees2Radians;
 
 /// Interpolate between [min] and [max] with the amount of [a] using a linear
 /// interpolation. The computation is equivalent to the GLSL function mix.
-double mix(double min, double max, double a) {
-  return min + a * (max - min);
-}
+double mix(double min, double max, double a) => min + a * (max - min);
 
 /// Do a smooth step (hermite interpolation) interpolation with [edge0] and
 /// [edge1] by [amount]. The computation is equivalent to the GLSL function
 /// smoothstep.
 double smoothStep(double edge0, double edge1, double amount) {
-  final t = ((amount - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
+  final double t =
+      ((amount - edge0) / (edge1 - edge0)).clamp(0.0, 1.0).toDouble();
 
   return t * t * (3.0 - 2.0 * t);
 }
 
 /// Do a catmull rom spline interpolation with [edge0], [edge1], [edge2] and
 /// [edge3] by [amount].
-double catmullRom(
-    double edge0, double edge1, double edge2, double edge3, double amount) {
-  return 0.5 *
-      ((2.0 * edge1) +
-          (-edge0 + edge2) * amount +
-          (2.0 * edge0 - 5.0 * edge1 + 4.0 * edge2 - edge3) *
-              (amount * amount) +
-          (-edge0 + 3.0 * edge1 - 3.0 * edge2 + edge3) *
-              (amount * amount * amount));
-}
+double catmullRom(double edge0, double edge1, double edge2, double edge3,
+        double amount) =>
+    0.5 *
+    ((2.0 * edge1) +
+        (-edge0 + edge2) * amount +
+        (2.0 * edge0 - 5.0 * edge1 + 4.0 * edge2 - edge3) * (amount * amount) +
+        (-edge0 + 3.0 * edge1 - 3.0 * edge2 + edge3) *
+            (amount * amount * amount));
diff --git a/pub/vector_math/lib/src/vector_math/vector.dart b/pub/vector_math/lib/src/vector_math/vector.dart
index 057fffe..a6952a4 100644
--- a/pub/vector_math/lib/src/vector_math/vector.dart
+++ b/pub/vector_math/lib/src/vector_math/vector.dart
@@ -20,41 +20,51 @@
 
 /// 2D cross product. double x vec2.
 void cross2A(double x, Vector2 y, Vector2 out) {
-  var tempy = x * y.x;
-  out.x = -x * y.y;
-  out.y = tempy;
+  final double tempy = x * y.x;
+  out
+    ..x = -x * y.y
+    ..y = tempy;
 }
 
 /// 2D cross product. vec2 x double.
 void cross2B(Vector2 x, double y, Vector2 out) {
-  var tempy = -y * x.x;
-  out.x = y * x.y;
-  out.y = tempy;
+  final double tempy = -y * x.x;
+  out
+    ..x = y * x.y
+    ..y = tempy;
 }
 
 /// Sets [u] and [v] to be two vectors orthogonal to each other and
 /// [planeNormal].
 void buildPlaneVectors(final Vector3 planeNormal, Vector3 u, Vector3 v) {
-  if (planeNormal.z.abs() > Math.SQRT1_2) {
+  if (planeNormal.z.abs() > math.SQRT1_2) {
     // choose u in y-z plane
-    double a = planeNormal.y * planeNormal.y + planeNormal.z * planeNormal.z;
-    double k = 1.0 / Math.sqrt(a);
-    u.x = 0.0;
-    u.y = -planeNormal.z * k;
-    u.z = planeNormal.y * k;
-    v.x = a * k;
-    v.y = -planeNormal[0] * (planeNormal[1] * k);
-    v.z = planeNormal[0] * (-planeNormal[2] * k);
+    final double a =
+        planeNormal.y * planeNormal.y + planeNormal.z * planeNormal.z;
+    final double k = 1.0 / math.sqrt(a);
+    u
+      ..x = 0.0
+      ..y = -planeNormal.z * k
+      ..z = planeNormal.y * k;
+
+    v
+      ..x = a * k
+      ..y = -planeNormal[0] * (planeNormal[1] * k)
+      ..z = planeNormal[0] * (-planeNormal[2] * k);
   } else {
     // choose u in x-y plane
-    double a = planeNormal.x * planeNormal.x + planeNormal.y * planeNormal.y;
-    double k = 1.0 / Math.sqrt(a);
-    u.x = -planeNormal[1] * k;
-    u.y = planeNormal[0] * k;
-    u.z = 0.0;
-    v.x = -planeNormal[2] * (planeNormal[0] * k);
-    v.y = planeNormal[2] * (-planeNormal[1] * k);
-    v.z = a * k;
+    final double a =
+        planeNormal.x * planeNormal.x + planeNormal.y * planeNormal.y;
+    final double k = 1.0 / math.sqrt(a);
+    u
+      ..x = -planeNormal[1] * k
+      ..y = planeNormal[0] * k
+      ..z = 0.0;
+
+    v
+      ..x = -planeNormal[2] * (planeNormal[0] * k)
+      ..y = planeNormal[2] * (-planeNormal[1] * k)
+      ..z = a * k;
   }
 }
 
diff --git a/pub/vector_math/lib/src/vector_math/vector2.dart b/pub/vector_math/lib/src/vector_math/vector2.dart
index d98ecec..30b6f13 100644
--- a/pub/vector_math/lib/src/vector_math/vector2.dart
+++ b/pub/vector_math/lib/src/vector_math/vector2.dart
@@ -9,25 +9,29 @@
   final Float32List _v2storage;
 
   /// The components of the vector.
+  @override
   Float32List get storage => _v2storage;
 
   /// Set the values of [result] to the minimum of [a] and [b] for each line.
   static void min(Vector2 a, Vector2 b, Vector2 result) {
-    result.x = Math.min(a.x, b.x);
-    result.y = Math.min(a.y, b.y);
+    result
+      ..x = math.min(a.x, b.x)
+      ..y = math.min(a.y, b.y);
   }
 
   /// Set the values of [result] to the maximum of [a] and [b] for each line.
   static void max(Vector2 a, Vector2 b, Vector2 result) {
-    result.x = Math.max(a.x, b.x);
-    result.y = Math.max(a.y, b.y);
+    result
+      ..x = math.max(a.x, b.x)
+      ..y = math.max(a.y, b.y);
   }
 
   /// Interpolate between [min] and [max] with the amount of [a] using a linear
   /// interpolation and store the values in [result].
   static void mix(Vector2 min, Vector2 max, double a, Vector2 result) {
-    result.x = min.x + a * (max.x - min.x);
-    result.y = min.y + a * (max.y - min.y);
+    result
+      ..x = min.x + a * (max.x - min.x)
+      ..y = min.y + a * (max.y - min.y);
   }
 
   /// Construct a new vector with the specified values.
@@ -56,8 +60,8 @@
 
   /// Generate random vector in the range (0, 0) to (1, 1). You can
   /// optionally pass your own random number generator.
-  factory Vector2.random([Math.Random rng]) {
-    rng = rng == null ? new Math.Random() : rng;
+  factory Vector2.random([math.Random rng]) {
+    rng = rng == null ? new math.Random() : rng;
     return new Vector2(rng.nextDouble(), rng.nextDouble());
   }
 
@@ -75,7 +79,7 @@
 
   /// Set the values by copying them from [other].
   void setFrom(Vector2 other) {
-    final otherStorage = other._v2storage;
+    final Float32List otherStorage = other._v2storage;
     _v2storage[1] = otherStorage[1];
     _v2storage[0] = otherStorage[0];
   }
@@ -87,15 +91,17 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[${_v2storage[0]},${_v2storage[1]}]';
 
   /// Check if two vectors are the same.
-  bool operator ==(other) {
-    return (other is Vector2) &&
-        (_v2storage[0] == other._v2storage[0]) &&
-        (_v2storage[1] == other._v2storage[1]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Vector2) &&
+      (_v2storage[0] == other._v2storage[0]) &&
+      (_v2storage[1] == other._v2storage[1]);
 
+  @override
   int get hashCode => quiver.hashObjects(_v2storage);
 
   /// Negate.
@@ -138,11 +144,11 @@
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Length squared.
   double get length2 {
-    var sum;
+    double sum;
     sum = (_v2storage[0] * _v2storage[0]);
     sum += (_v2storage[1] * _v2storage[1]);
     return sum;
@@ -150,11 +156,11 @@
 
   /// Normalize [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _v2storage[0] *= d;
     _v2storage[1] *= d;
     return l;
@@ -177,69 +183,67 @@
   }
 
   /// Distance from [this] to [arg]
-  double distanceTo(Vector2 arg) => Math.sqrt(distanceToSquared(arg));
+  double distanceTo(Vector2 arg) => math.sqrt(distanceToSquared(arg));
 
   /// Squared distance from [this] to [arg]
   double distanceToSquared(Vector2 arg) {
-    final dx = x - arg.x;
-    final dy = y - arg.y;
+    final double dx = x - arg.x;
+    final double dy = y - arg.y;
 
     return dx * dx + dy * dy;
   }
 
   /// Returns the angle between [this] vector and [other] in radians.
   double angleTo(Vector2 other) {
-    final otherStorage = other._v2storage;
-    if (_v2storage[0] == otherStorage[0] &&
-        _v2storage[1] == otherStorage[1]) {
+    final Float32List otherStorage = other._v2storage;
+    if (_v2storage[0] == otherStorage[0] && _v2storage[1] == otherStorage[1]) {
       return 0.0;
     }
 
-    final d = dot(other);
+    final double d = dot(other);
 
-    return Math.acos(d.clamp(-1.0, 1.0));
+    return math.acos(d.clamp(-1.0, 1.0));
   }
 
   /// Returns the signed angle between [this] and [other] in radians.
   double angleToSigned(Vector2 other) {
-    final otherStorage = other._v2storage;
-    if (_v2storage[0] == otherStorage[0] &&
-        _v2storage[1] == otherStorage[1]) {
+    final Float32List otherStorage = other._v2storage;
+    if (_v2storage[0] == otherStorage[0] && _v2storage[1] == otherStorage[1]) {
       return 0.0;
     }
 
-    final s = cross(other);
-    final c = dot(other);
+    final double s = cross(other);
+    final double c = dot(other);
 
-    return Math.atan2(s, c);
+    return math.atan2(s, c);
   }
 
   /// Inner product.
   double dot(Vector2 other) {
-    final otherStorage = other._v2storage;
+    final Float32List otherStorage = other._v2storage;
     double sum;
     sum = _v2storage[0] * otherStorage[0];
     sum += _v2storage[1] * otherStorage[1];
     return sum;
   }
 
-  /**
-   * Transforms [this] into the product of [this] as a row vector,
-   * postmultiplied by matrix, [arg].
-   * If [arg] is a rotation matrix, this is a computational shortcut for applying,
-   * the inverse of the transformation.
-   */
+  ///
+  /// Transforms [this] into the product of [this] as a row vector,
+  /// postmultiplied by matrix, [arg].
+  /// If [arg] is a rotation matrix, this is a computational shortcut for applying,
+  /// the inverse of the transformation.
+  ///
   void postmultiply(Matrix2 arg) {
-    final argStorage = arg.storage;
-    double v0 = _v2storage[0];
-    double v1 = _v2storage[1];
+    final Float32List argStorage = arg.storage;
+    final double v0 = _v2storage[0];
+    final double v1 = _v2storage[1];
     _v2storage[0] = v0 * argStorage[0] + v1 * argStorage[1];
     _v2storage[1] = v0 * argStorage[2] + v1 * argStorage[3];
   }
 
   /// Cross product.
   double cross(Vector2 other) {
-    final otherStorage = other._v2storage;
+    final Float32List otherStorage = other._v2storage;
     return _v2storage[0] * otherStorage[1] - _v2storage[1] * otherStorage[0];
   }
 
@@ -259,15 +263,13 @@
 
   /// Relative error between [this] and [correct]
   double relativeError(Vector2 correct) {
-    double correct_norm = correct.length;
-    double diff_norm = (this - correct).length;
+    final double correct_norm = correct.length;
+    final double diff_norm = (this - correct).length;
     return diff_norm / correct_norm;
   }
 
   /// Absolute error between [this] and [correct]
-  double absoluteError(Vector2 correct) {
-    return (this - correct).length;
-  }
+  double absoluteError(Vector2 correct) => (this - correct).length;
 
   /// True if any component is infinite.
   bool get isInfinite {
@@ -287,35 +289,35 @@
 
   /// Add [arg] to [this].
   void add(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] + argStorage[0];
     _v2storage[1] = _v2storage[1] + argStorage[1];
   }
 
   /// Add [arg] scaled by [factor] to [this].
   void addScaled(Vector2 arg, double factor) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] + argStorage[0] * factor;
     _v2storage[1] = _v2storage[1] + argStorage[1] * factor;
   }
 
   /// Subtract [arg] from [this].
   void sub(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] - argStorage[0];
     _v2storage[1] = _v2storage[1] - argStorage[1];
   }
 
   /// Multiply entries in [this] with entries in [arg].
   void multiply(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] * argStorage[0];
     _v2storage[1] = _v2storage[1] * argStorage[1];
   }
 
   /// Divide entries in [this] with entries in [arg].
   void divide(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] / argStorage[0];
     _v2storage[1] = _v2storage[1] / argStorage[1];
   }
@@ -343,16 +345,18 @@
 
   /// Clamp each entry n in [this] in the range [min[n]]-[max[n]].
   void clamp(Vector2 min, Vector2 max) {
-    var minStorage = min.storage;
-    var maxStorage = max.storage;
-    _v2storage[0] = _v2storage[0].clamp(minStorage[0], maxStorage[0]);
-    _v2storage[1] = _v2storage[1].clamp(minStorage[1], maxStorage[1]);
+    final Float32List minStorage = min.storage;
+    final Float32List maxStorage = max.storage;
+    _v2storage[0] =
+        _v2storage[0].clamp(minStorage[0], maxStorage[0]).toDouble();
+    _v2storage[1] =
+        _v2storage[1].clamp(minStorage[1], maxStorage[1]).toDouble();
   }
 
   /// Clamp entries [this] in the range [min]-[max].
   void clampScalar(double min, double max) {
-    _v2storage[0] = _v2storage[0].clamp(min, max);
-    _v2storage[1] = _v2storage[1].clamp(min, max);
+    _v2storage[0] = _v2storage[0].clamp(min, max).toDouble();
+    _v2storage[1] = _v2storage[1].clamp(min, max).toDouble();
   }
 
   /// Floor entries in [this].
@@ -388,7 +392,7 @@
 
   /// Copy [this] into [arg]. Returns [arg].
   Vector2 copyInto(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     argStorage[1] = _v2storage[1];
     argStorage[0] = _v2storage[0];
     return arg;
@@ -407,13 +411,13 @@
   }
 
   set xy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v2storage[0] = argStorage[0];
     _v2storage[1] = argStorage[1];
   }
 
   set yx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v2storage[1] = argStorage[0];
     _v2storage[0] = argStorage[1];
   }
diff --git a/pub/vector_math/lib/src/vector_math/vector3.dart b/pub/vector_math/lib/src/vector_math/vector3.dart
index 3f5177d..d2644fa 100644
--- a/pub/vector_math/lib/src/vector_math/vector3.dart
+++ b/pub/vector_math/lib/src/vector_math/vector3.dart
@@ -9,28 +9,32 @@
   final Float32List _v3storage;
 
   /// The components of the vector.
+  @override
   Float32List get storage => _v3storage;
 
   /// Set the values of [result] to the minimum of [a] and [b] for each line.
   static void min(Vector3 a, Vector3 b, Vector3 result) {
-    result.x = Math.min(a.x, b.x);
-    result.y = Math.min(a.y, b.y);
-    result.z = Math.min(a.z, b.z);
+    result
+      ..x = math.min(a.x, b.x)
+      ..y = math.min(a.y, b.y)
+      ..z = math.min(a.z, b.z);
   }
 
   /// Set the values of [result] to the maximum of [a] and [b] for each line.
   static void max(Vector3 a, Vector3 b, Vector3 result) {
-    result.x = Math.max(a.x, b.x);
-    result.y = Math.max(a.y, b.y);
-    result.z = Math.max(a.z, b.z);
+    result
+      ..x = math.max(a.x, b.x)
+      ..y = math.max(a.y, b.y)
+      ..z = math.max(a.z, b.z);
   }
 
   /// Interpolate between [min] and [max] with the amount of [a] using a linear
   /// interpolation and store the values in [result].
   static void mix(Vector3 min, Vector3 max, double a, Vector3 result) {
-    result.x = min.x + a * (max.x - min.x);
-    result.y = min.y + a * (max.y - min.y);
-    result.z = min.z + a * (max.z - min.z);
+    result
+      ..x = min.x + a * (max.x - min.x)
+      ..y = min.y + a * (max.y - min.y)
+      ..z = min.z + a * (max.z - min.z);
   }
 
   /// Construct a new vector with the specified values.
@@ -60,8 +64,8 @@
 
   /// Generate random vector in the range (0, 0, 0) to (1, 1, 1). You can
   /// optionally pass your own random number generator.
-  factory Vector3.random([Math.Random rng]) {
-    rng = rng == null ? new Math.Random() : rng;
+  factory Vector3.random([math.Random rng]) {
+    rng = rng == null ? new math.Random() : rng;
     return new Vector3(rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
   }
 
@@ -81,7 +85,7 @@
 
   /// Set the values by copying them from [other].
   void setFrom(Vector3 other) {
-    final otherStorage = other._v3storage;
+    final Float32List otherStorage = other._v3storage;
     _v3storage[0] = otherStorage[0];
     _v3storage[1] = otherStorage[1];
     _v3storage[2] = otherStorage[2];
@@ -95,16 +99,18 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[${storage[0]},${storage[1]},${storage[2]}]';
 
   /// Check if two vectors are the same.
-  bool operator ==(other) {
-    return (other is Vector3) &&
-        (_v3storage[0] == other._v3storage[0]) &&
-        (_v3storage[1] == other._v3storage[1]) &&
-        (_v3storage[2] == other._v3storage[2]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Vector3) &&
+      (_v3storage[0] == other._v3storage[0]) &&
+      (_v3storage[1] == other._v3storage[1]) &&
+      (_v3storage[2] == other._v3storage[2]);
 
+  @override
   int get hashCode => quiver.hashObjects(_v3storage);
 
   /// Negate
@@ -148,7 +154,7 @@
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Length squared.
   double get length2 {
@@ -161,11 +167,11 @@
 
   /// Normalizes [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _v3storage[0] *= d;
     _v3storage[1] *= d;
     _v3storage[2] *= d;
@@ -189,45 +195,45 @@
   }
 
   /// Distance from [this] to [arg]
-  double distanceTo(Vector3 arg) => Math.sqrt(distanceToSquared(arg));
+  double distanceTo(Vector3 arg) => math.sqrt(distanceToSquared(arg));
 
   /// Squared distance from [this] to [arg]
   double distanceToSquared(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final dx = _v3storage[0] - argStorage[0];
-    final dy = _v3storage[1] - argStorage[1];
-    final dz = _v3storage[2] - argStorage[2];
+    final Float32List argStorage = arg._v3storage;
+    final double dx = _v3storage[0] - argStorage[0];
+    final double dy = _v3storage[1] - argStorage[1];
+    final double dz = _v3storage[2] - argStorage[2];
 
     return dx * dx + dy * dy + dz * dz;
   }
 
   /// Returns the angle between [this] vector and [other] in radians.
   double angleTo(Vector3 other) {
-    final otherStorage = other._v3storage;
+    final Float32List otherStorage = other._v3storage;
     if (_v3storage[0] == otherStorage[0] &&
         _v3storage[1] == otherStorage[1] &&
         _v3storage[2] == otherStorage[2]) {
       return 0.0;
     }
 
-    final d = dot(other);
+    final double d = dot(other);
 
-    return Math.acos(d.clamp(-1.0, 1.0));
+    return math.acos(d.clamp(-1.0, 1.0));
   }
 
   /// Returns the signed angle between [this] and [other] around [normal]
   /// in radians.
   double angleToSigned(Vector3 other, Vector3 normal) {
-    final angle = angleTo(other);
-    final c = cross(other);
-    final d = c.dot(normal);
+    final double angle = angleTo(other);
+    final Vector3 c = cross(other);
+    final double d = c.dot(normal);
 
     return d < 0.0 ? -angle : angle;
   }
 
   /// Inner product.
   double dot(Vector3 other) {
-    final otherStorage = other._v3storage;
+    final Float32List otherStorage = other._v3storage;
     double sum;
     sum = _v3storage[0] * otherStorage[0];
     sum += _v3storage[1] * otherStorage[1];
@@ -240,10 +246,10 @@
   /// If [arg] is a rotation matrix, this is a computational shortcut for applying,
   /// the inverse of the transformation.
   void postmultiply(Matrix3 arg) {
-    final argStorage = arg.storage;
-    final v0 = _v3storage[0];
-    final v1 = _v3storage[1];
-    final v2 = _v3storage[2];
+    final Float32List argStorage = arg.storage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
 
     _v3storage[0] =
         v0 * argStorage[0] + v1 * argStorage[1] + v2 * argStorage[2];
@@ -255,26 +261,26 @@
 
   /// Cross product.
   Vector3 cross(Vector3 other) {
-    final _x = _v3storage[0];
-    final _y = _v3storage[1];
-    final _z = _v3storage[2];
-    final otherStorage = other._v3storage;
-    final ox = otherStorage[0];
-    final oy = otherStorage[1];
-    final oz = otherStorage[2];
+    final double _x = _v3storage[0];
+    final double _y = _v3storage[1];
+    final double _z = _v3storage[2];
+    final Float32List otherStorage = other._v3storage;
+    final double ox = otherStorage[0];
+    final double oy = otherStorage[1];
+    final double oz = otherStorage[2];
     return new Vector3(_y * oz - _z * oy, _z * ox - _x * oz, _x * oy - _y * ox);
   }
 
   /// Cross product. Stores result in [out].
   Vector3 crossInto(Vector3 other, Vector3 out) {
-    final x = _v3storage[0];
-    final y = _v3storage[1];
-    final z = _v3storage[2];
-    final otherStorage = other._v3storage;
-    final ox = otherStorage[0];
-    final oy = otherStorage[1];
-    final oz = otherStorage[2];
-    final outStorage = out._v3storage;
+    final double x = _v3storage[0];
+    final double y = _v3storage[1];
+    final double z = _v3storage[2];
+    final Float32List otherStorage = other._v3storage;
+    final double ox = otherStorage[0];
+    final double oy = otherStorage[1];
+    final double oz = otherStorage[2];
+    final Float32List outStorage = out._v3storage;
     outStorage[0] = y * oz - z * oy;
     outStorage[1] = z * ox - x * oz;
     outStorage[2] = x * oy - y * ox;
@@ -291,11 +297,11 @@
 
   /// Projects [this] using the projection matrix [arg]
   void applyProjection(Matrix4 arg) {
-    final argStorage = arg.storage;
-    final x = _v3storage[0];
-    final y = _v3storage[1];
-    final z = _v3storage[2];
-    final d = 1.0 /
+    final Float32List argStorage = arg.storage;
+    final double x = _v3storage[0];
+    final double y = _v3storage[1];
+    final double z = _v3storage[2];
+    final double d = 1.0 /
         (argStorage[3] * x +
             argStorage[7] * y +
             argStorage[11] * z +
@@ -324,18 +330,18 @@
 
   /// Applies a quaternion transform.
   void applyQuaternion(Quaternion arg) {
-    final argStorage = arg._qStorage;
-    var v0 = _v3storage[0];
-    var v1 = _v3storage[1];
-    var v2 = _v3storage[2];
-    var qx = argStorage[0];
-    var qy = argStorage[1];
-    var qz = argStorage[2];
-    var qw = argStorage[3];
-    var ix = qw * v0 + qy * v2 - qz * v1;
-    var iy = qw * v1 + qz * v0 - qx * v2;
-    var iz = qw * v2 + qx * v1 - qy * v0;
-    var iw = -qx * v0 - qy * v1 - qz * v2;
+    final Float32List argStorage = arg._qStorage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
+    final double qx = argStorage[0];
+    final double qy = argStorage[1];
+    final double qz = argStorage[2];
+    final double qw = argStorage[3];
+    final double ix = qw * v0 + qy * v2 - qz * v1;
+    final double iy = qw * v1 + qz * v0 - qx * v2;
+    final double iz = qw * v2 + qx * v1 - qy * v0;
+    final double iw = -qx * v0 - qy * v1 - qz * v2;
     _v3storage[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
     _v3storage[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
     _v3storage[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
@@ -343,10 +349,10 @@
 
   /// Multiplies [this] by [arg].
   void applyMatrix3(Matrix3 arg) {
-    final argStorage = arg.storage;
-    var v0 = _v3storage[0];
-    var v1 = _v3storage[1];
-    var v2 = _v3storage[2];
+    final Float32List argStorage = arg.storage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
     _v3storage[0] =
         argStorage[0] * v0 + argStorage[3] * v1 + argStorage[6] * v2;
     _v3storage[1] =
@@ -358,10 +364,10 @@
   /// Multiplies [this] by a 4x3 subset of [arg]. Expects [arg] to be an affine
   /// transformation matrix.
   void applyMatrix4(Matrix4 arg) {
-    final argStorage = arg.storage;
-    var v0 = _v3storage[0];
-    var v1 = _v3storage[1];
-    var v2 = _v3storage[2];
+    final Float32List argStorage = arg.storage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
     _v3storage[0] = argStorage[0] * v0 +
         argStorage[4] * v1 +
         argStorage[8] * v2 +
@@ -378,15 +384,13 @@
 
   /// Relative error between [this] and [correct]
   double relativeError(Vector3 correct) {
-    double correct_norm = correct.length;
-    double diff_norm = (this - correct).length;
+    final double correct_norm = correct.length;
+    final double diff_norm = (this - correct).length;
     return diff_norm / correct_norm;
   }
 
   /// Absolute error between [this] and [correct]
-  double absoluteError(Vector3 correct) {
-    return (this - correct).length;
-  }
+  double absoluteError(Vector3 correct) => (this - correct).length;
 
   /// True if any component is infinite.
   bool get isInfinite {
@@ -408,7 +412,7 @@
 
   /// Add [arg] to [this].
   void add(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] + argStorage[0];
     _v3storage[1] = _v3storage[1] + argStorage[1];
     _v3storage[2] = _v3storage[2] + argStorage[2];
@@ -416,7 +420,7 @@
 
   /// Add [arg] scaled by [factor] to [this].
   void addScaled(Vector3 arg, double factor) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] + argStorage[0] * factor;
     _v3storage[1] = _v3storage[1] + argStorage[1] * factor;
     _v3storage[2] = _v3storage[2] + argStorage[2] * factor;
@@ -424,7 +428,7 @@
 
   /// Subtract [arg] from [this].
   void sub(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] - argStorage[0];
     _v3storage[1] = _v3storage[1] - argStorage[1];
     _v3storage[2] = _v3storage[2] - argStorage[2];
@@ -432,7 +436,7 @@
 
   /// Multiply entries in [this] with entries in [arg].
   void multiply(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] * argStorage[0];
     _v3storage[1] = _v3storage[1] * argStorage[1];
     _v3storage[2] = _v3storage[2] * argStorage[2];
@@ -440,7 +444,7 @@
 
   /// Divide entries in [this] with entries in [arg].
   void divide(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] / argStorage[0];
     _v3storage[1] = _v3storage[1] / argStorage[1];
     _v3storage[2] = _v3storage[2] / argStorage[2];
@@ -472,18 +476,21 @@
 
   /// Clamp each entry n in [this] in the range [min[n]]-[max[n]].
   void clamp(Vector3 min, Vector3 max) {
-    final minStorage = min.storage;
-    final maxStorage = max.storage;
-    _v3storage[0] = _v3storage[0].clamp(minStorage[0], maxStorage[0]);
-    _v3storage[1] = _v3storage[1].clamp(minStorage[1], maxStorage[1]);
-    _v3storage[2] = _v3storage[2].clamp(minStorage[2], maxStorage[2]);
+    final Float32List minStorage = min.storage;
+    final Float32List maxStorage = max.storage;
+    _v3storage[0] =
+        _v3storage[0].clamp(minStorage[0], maxStorage[0]).toDouble();
+    _v3storage[1] =
+        _v3storage[1].clamp(minStorage[1], maxStorage[1]).toDouble();
+    _v3storage[2] =
+        _v3storage[2].clamp(minStorage[2], maxStorage[2]).toDouble();
   }
 
   /// Clamp entries in [this] in the range [min]-[max].
   void clampScalar(double min, double max) {
-    _v3storage[0] = _v3storage[0].clamp(min, max);
-    _v3storage[1] = _v3storage[1].clamp(min, max);
-    _v3storage[2] = _v3storage[2].clamp(min, max);
+    _v3storage[0] = _v3storage[0].clamp(min, max).toDouble();
+    _v3storage[1] = _v3storage[1].clamp(min, max).toDouble();
+    _v3storage[2] = _v3storage[2].clamp(min, max).toDouble();
   }
 
   /// Floor entries in [this].
@@ -525,7 +532,7 @@
 
   /// Copy [this] into [arg].
   Vector3 copyInto(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     argStorage[0] = _v3storage[0];
     argStorage[1] = _v3storage[1];
     argStorage[2] = _v3storage[2];
@@ -547,78 +554,78 @@
   }
 
   set xy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v3storage[0] = argStorage[0];
     _v3storage[1] = argStorage[1];
   }
 
   set xz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v3storage[0] = argStorage[0];
     _v3storage[2] = argStorage[1];
   }
 
   set yx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v3storage[1] = argStorage[0];
     _v3storage[0] = argStorage[1];
   }
 
   set yz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v3storage[1] = argStorage[0];
     _v3storage[2] = argStorage[1];
   }
 
   set zx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v3storage[2] = argStorage[0];
     _v3storage[0] = argStorage[1];
   }
 
   set zy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v3storage[2] = argStorage[0];
     _v3storage[1] = argStorage[1];
   }
 
   set xyz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[0] = argStorage[0];
     _v3storage[1] = argStorage[1];
     _v3storage[2] = argStorage[2];
   }
 
   set xzy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[0] = argStorage[0];
     _v3storage[2] = argStorage[1];
     _v3storage[1] = argStorage[2];
   }
 
   set yxz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[1] = argStorage[0];
     _v3storage[0] = argStorage[1];
     _v3storage[2] = argStorage[2];
   }
 
   set yzx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[1] = argStorage[0];
     _v3storage[2] = argStorage[1];
     _v3storage[0] = argStorage[2];
   }
 
   set zxy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[2] = argStorage[0];
     _v3storage[0] = argStorage[1];
     _v3storage[1] = argStorage[2];
   }
 
   set zyx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v3storage[2] = argStorage[0];
     _v3storage[1] = argStorage[1];
     _v3storage[0] = argStorage[2];
diff --git a/pub/vector_math/lib/src/vector_math/vector4.dart b/pub/vector_math/lib/src/vector_math/vector4.dart
index 72a2496..e1f312a 100644
--- a/pub/vector_math/lib/src/vector_math/vector4.dart
+++ b/pub/vector_math/lib/src/vector_math/vector4.dart
@@ -10,30 +10,34 @@
 
   /// Set the values of [result] to the minimum of [a] and [b] for each line.
   static void min(Vector4 a, Vector4 b, Vector4 result) {
-    result.x = Math.min(a.x, b.x);
-    result.y = Math.min(a.y, b.y);
-    result.z = Math.min(a.z, b.z);
-    result.w = Math.min(a.w, b.w);
+    result
+      ..x = math.min(a.x, b.x)
+      ..y = math.min(a.y, b.y)
+      ..z = math.min(a.z, b.z)
+      ..w = math.min(a.w, b.w);
   }
 
   /// Set the values of [result] to the maximum of [a] and [b] for each line.
   static void max(Vector4 a, Vector4 b, Vector4 result) {
-    result.x = Math.max(a.x, b.x);
-    result.y = Math.max(a.y, b.y);
-    result.z = Math.max(a.z, b.z);
-    result.w = Math.max(a.w, b.w);
+    result
+      ..x = math.max(a.x, b.x)
+      ..y = math.max(a.y, b.y)
+      ..z = math.max(a.z, b.z)
+      ..w = math.max(a.w, b.w);
   }
 
   /// Interpolate between [min] and [max] with the amount of [a] using a linear
   /// interpolation and store the values in [result].
   static void mix(Vector4 min, Vector4 max, double a, Vector4 result) {
-    result.x = min.x + a * (max.x - min.x);
-    result.y = min.y + a * (max.y - min.y);
-    result.z = min.z + a * (max.z - min.z);
-    result.w = min.w + a * (max.w - min.w);
+    result
+      ..x = min.x + a * (max.x - min.x)
+      ..y = min.y + a * (max.y - min.y)
+      ..z = min.z + a * (max.z - min.z)
+      ..w = min.w + a * (max.w - min.w);
   }
 
   /// The components of the vector.
+  @override
   Float32List get storage => _v4storage;
 
   /// Construct a new vector with the specified values.
@@ -66,10 +70,10 @@
 
   /// Generate random vector in the range (0, 0, 0, 0) to (1, 1, 1, 1). You can
   /// optionally pass your own random number generator.
-  factory Vector4.random([Math.Random rng]) {
-    rng = rng == null ? new Math.Random() : rng;
+  factory Vector4.random([math.Random rng]) {
+    rng = rng == null ? new math.Random() : rng;
     return new Vector4(
-      rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
+        rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
   }
 
   /// Set the values of the vector.
@@ -98,7 +102,7 @@
 
   /// Set the values by copying them from [other].
   void setFrom(Vector4 other) {
-    final otherStorage = other._v4storage;
+    final Float32List otherStorage = other._v4storage;
     _v4storage[3] = otherStorage[3];
     _v4storage[2] = otherStorage[2];
     _v4storage[1] = otherStorage[1];
@@ -114,18 +118,20 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '${_v4storage[0]},${_v4storage[1]},'
       '${_v4storage[2]},${_v4storage[3]}';
 
   /// Check if two vectors are the same.
-  bool operator ==(other) {
-    return (other is Vector4) &&
-        (_v4storage[0] == other._v4storage[0]) &&
-        (_v4storage[1] == other._v4storage[1]) &&
-        (_v4storage[2] == other._v4storage[2]) &&
-        (_v4storage[3] == other._v4storage[3]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Vector4) &&
+      (_v4storage[0] == other._v4storage[0]) &&
+      (_v4storage[1] == other._v4storage[1]) &&
+      (_v4storage[2] == other._v4storage[2]) &&
+      (_v4storage[3] == other._v4storage[3]);
 
+  @override
   int get hashCode => quiver.hashObjects(_v4storage);
 
   /// Negate.
@@ -170,7 +176,7 @@
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Length squared.
   double get length2 {
@@ -184,11 +190,11 @@
 
   /// Normalizes [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _v4storage[0] *= d;
     _v4storage[1] *= d;
     _v4storage[2] *= d;
@@ -213,22 +219,22 @@
   }
 
   /// Distance from [this] to [arg]
-  double distanceTo(Vector4 arg) => Math.sqrt(distanceToSquared(arg));
+  double distanceTo(Vector4 arg) => math.sqrt(distanceToSquared(arg));
 
   /// Squared distance from [this] to [arg]
   double distanceToSquared(Vector4 arg) {
-    final argStorage = arg._v4storage;
-    final dx = _v4storage[0] - argStorage[0];
-    final dy = _v4storage[1] - argStorage[1];
-    final dz = _v4storage[2] - argStorage[2];
-    final dw = _v4storage[3] - argStorage[3];
+    final Float32List argStorage = arg._v4storage;
+    final double dx = _v4storage[0] - argStorage[0];
+    final double dy = _v4storage[1] - argStorage[1];
+    final double dz = _v4storage[2] - argStorage[2];
+    final double dw = _v4storage[3] - argStorage[3];
 
     return dx * dx + dy * dy + dz * dz + dw * dw;
   }
 
   /// Inner product.
   double dot(Vector4 other) {
-    final otherStorage = other._v4storage;
+    final Float32List otherStorage = other._v4storage;
     double sum;
     sum = _v4storage[0] * otherStorage[0];
     sum += _v4storage[1] * otherStorage[1];
@@ -239,11 +245,11 @@
 
   /// Multiplies [this] by [arg].
   void applyMatrix4(Matrix4 arg) {
-    var v1 = _v4storage[0];
-    var v2 = _v4storage[1];
-    var v3 = _v4storage[2];
-    var v4 = _v4storage[3];
-    final argStorage = arg.storage;
+    final double v1 = _v4storage[0];
+    final double v2 = _v4storage[1];
+    final double v3 = _v4storage[2];
+    final double v4 = _v4storage[3];
+    final Float32List argStorage = arg.storage;
     _v4storage[0] = argStorage[0] * v1 +
         argStorage[4] * v2 +
         argStorage[8] * v3 +
@@ -264,15 +270,13 @@
 
   /// Relative error between [this] and [correct]
   double relativeError(Vector4 correct) {
-    double correct_norm = correct.length;
-    double diff_norm = (this - correct).length;
+    final double correct_norm = correct.length;
+    final double diff_norm = (this - correct).length;
     return diff_norm / correct_norm;
   }
 
   /// Absolute error between [this] and [correct]
-  double absoluteError(Vector4 correct) {
-    return (this - correct).length;
-  }
+  double absoluteError(Vector4 correct) => (this - correct).length;
 
   /// True if any component is infinite.
   bool get isInfinite {
@@ -295,7 +299,7 @@
   }
 
   void add(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] + argStorage[0];
     _v4storage[1] = _v4storage[1] + argStorage[1];
     _v4storage[2] = _v4storage[2] + argStorage[2];
@@ -304,7 +308,7 @@
 
   /// Add [arg] scaled by [factor] to [this].
   void addScaled(Vector4 arg, double factor) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] + argStorage[0] * factor;
     _v4storage[1] = _v4storage[1] + argStorage[1] * factor;
     _v4storage[2] = _v4storage[2] + argStorage[2] * factor;
@@ -313,7 +317,7 @@
 
   /// Subtract [arg] from [this].
   void sub(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] - argStorage[0];
     _v4storage[1] = _v4storage[1] - argStorage[1];
     _v4storage[2] = _v4storage[2] - argStorage[2];
@@ -322,7 +326,7 @@
 
   /// Multiply [this] by [arg].
   void multiply(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] * argStorage[0];
     _v4storage[1] = _v4storage[1] * argStorage[1];
     _v4storage[2] = _v4storage[2] * argStorage[2];
@@ -331,7 +335,7 @@
 
   /// Divide [this] by [arg].
   void div(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] / argStorage[0];
     _v4storage[1] = _v4storage[1] / argStorage[1];
     _v4storage[2] = _v4storage[2] / argStorage[2];
@@ -367,20 +371,24 @@
 
   /// Clamp each entry n in [this] in the range [min[n]]-[max[n]].
   void clamp(Vector4 min, Vector4 max) {
-    final minStorage = min.storage;
-    final maxStorage = max.storage;
-    _v4storage[0] = _v4storage[0].clamp(minStorage[0], maxStorage[0]);
-    _v4storage[1] = _v4storage[1].clamp(minStorage[1], maxStorage[1]);
-    _v4storage[2] = _v4storage[2].clamp(minStorage[2], maxStorage[2]);
-    _v4storage[3] = _v4storage[3].clamp(minStorage[3], maxStorage[3]);
+    final Float32List minStorage = min.storage;
+    final Float32List maxStorage = max.storage;
+    _v4storage[0] =
+        _v4storage[0].clamp(minStorage[0], maxStorage[0]).toDouble();
+    _v4storage[1] =
+        _v4storage[1].clamp(minStorage[1], maxStorage[1]).toDouble();
+    _v4storage[2] =
+        _v4storage[2].clamp(minStorage[2], maxStorage[2]).toDouble();
+    _v4storage[3] =
+        _v4storage[3].clamp(minStorage[3], maxStorage[3]).toDouble();
   }
 
   /// Clamp entries in [this] in the range [min]-[max].
   void clampScalar(double min, double max) {
-    _v4storage[0] = _v4storage[0].clamp(min, max);
-    _v4storage[1] = _v4storage[1].clamp(min, max);
-    _v4storage[2] = _v4storage[2].clamp(min, max);
-    _v4storage[3] = _v4storage[3].clamp(min, max);
+    _v4storage[0] = _v4storage[0].clamp(min, max).toDouble();
+    _v4storage[1] = _v4storage[1].clamp(min, max).toDouble();
+    _v4storage[2] = _v4storage[2].clamp(min, max).toDouble();
+    _v4storage[3] = _v4storage[3].clamp(min, max).toDouble();
   }
 
   /// Floor entries in [this].
@@ -428,7 +436,7 @@
 
   /// Copy [this]
   Vector4 copyInto(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     argStorage[0] = _v4storage[0];
     argStorage[1] = _v4storage[1];
     argStorage[2] = _v4storage[2];
@@ -453,247 +461,247 @@
   }
 
   set xy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
   }
 
   set xz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
   }
 
   set xw(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
   }
 
   set yx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
   }
 
   set yz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
   }
 
   set yw(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
   }
 
   set zx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
   }
 
   set zy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
   }
 
   set zw(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
   }
 
   set wx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
   }
 
   set wy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
   }
 
   set wz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float32List argStorage = arg._v2storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
   }
 
   set xyz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set xyw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set xzy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set xzw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set xwy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set xwz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set yxz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set yxw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set yzx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set yzw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set ywx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set ywz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set zxy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set zxw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set zyx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set zyw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set zwx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set zwy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set wxy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set wxz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set wyx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set wyz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set wzx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set wzy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float32List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set xyzw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -701,7 +709,7 @@
   }
 
   set xywz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -709,7 +717,7 @@
   }
 
   set xzyw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -717,7 +725,7 @@
   }
 
   set xzwy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -725,7 +733,7 @@
   }
 
   set xwyz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -733,7 +741,7 @@
   }
 
   set xwzy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -741,7 +749,7 @@
   }
 
   set yxzw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -749,7 +757,7 @@
   }
 
   set yxwz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -757,7 +765,7 @@
   }
 
   set yzxw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -765,7 +773,7 @@
   }
 
   set yzwx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -773,7 +781,7 @@
   }
 
   set ywxz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -781,7 +789,7 @@
   }
 
   set ywzx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -789,7 +797,7 @@
   }
 
   set zxyw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -797,7 +805,7 @@
   }
 
   set zxwy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -805,7 +813,7 @@
   }
 
   set zyxw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -813,7 +821,7 @@
   }
 
   set zywx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -821,7 +829,7 @@
   }
 
   set zwxy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -829,7 +837,7 @@
   }
 
   set zwyx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -837,7 +845,7 @@
   }
 
   set wxyz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -845,7 +853,7 @@
   }
 
   set wxzy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -853,7 +861,7 @@
   }
 
   set wyxz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -861,7 +869,7 @@
   }
 
   set wyzx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -869,7 +877,7 @@
   }
 
   set wzxy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -877,7 +885,7 @@
   }
 
   set wzyx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float32List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
diff --git a/pub/vector_math/lib/src/vector_math_64/aabb2.dart b/pub/vector_math/lib/src/vector_math_64/aabb2.dart
index c0f86a1..11e4215 100644
--- a/pub/vector_math/lib/src/vector_math_64/aabb2.dart
+++ b/pub/vector_math/lib/src/vector_math_64/aabb2.dart
@@ -78,8 +78,8 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix3 t) {
-    final center = new Vector2.zero();
-    final halfExtents = new Vector2.zero();
+    final Vector2 center = new Vector2.zero();
+    final Vector2 halfExtents = new Vector2.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t
       ..transform2(center)
@@ -94,8 +94,8 @@
 
   /// Rotate [this] by the rotation matrix [t].
   void rotate(Matrix3 t) {
-    final center = new Vector2.zero();
-    final halfExtents = new Vector2.zero();
+    final Vector2 center = new Vector2.zero();
+    final Vector2 halfExtents = new Vector2.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t.absoluteRotate2(halfExtents);
     _min
@@ -133,8 +133,8 @@
 
   /// Return if [this] contains [other].
   bool containsAabb2(Aabb2 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector2 otherMax = other._max;
+    final Vector2 otherMin = other._min;
 
     return (_min.x < otherMin.x) &&
         (_min.y < otherMin.y) &&
@@ -143,17 +143,16 @@
   }
 
   /// Return if [this] contains [other].
-  bool containsVector2(Vector2 other) {
-    return (_min.x < other.x) &&
-        (_min.y < other.y) &&
-        (_max.x > other.x) &&
-        (_max.y > other.y);
-  }
+  bool containsVector2(Vector2 other) =>
+      (_min.x < other.x) &&
+      (_min.y < other.y) &&
+      (_max.x > other.x) &&
+      (_max.y > other.y);
 
   /// Return if [this] intersects with [other].
   bool intersectsWithAabb2(Aabb2 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector2 otherMax = other._max;
+    final Vector2 otherMin = other._min;
 
     return (_min.x <= otherMax.x) &&
         (_min.y <= otherMax.y) &&
@@ -162,10 +161,9 @@
   }
 
   /// Return if [this] intersects with [other].
-  bool intersectsWithVector2(Vector2 other) {
-    return (_min.x <= other.x) &&
-        (_min.y <= other.y) &&
-        (_max.x >= other.x) &&
-        (_max.y >= other.y);
-  }
+  bool intersectsWithVector2(Vector2 other) =>
+      (_min.x <= other.x) &&
+      (_min.y <= other.y) &&
+      (_max.x >= other.x) &&
+      (_max.y >= other.y);
 }
diff --git a/pub/vector_math/lib/src/vector_math_64/aabb3.dart b/pub/vector_math/lib/src/vector_math_64/aabb3.dart
index ecd3f10..189cad5 100644
--- a/pub/vector_math/lib/src/vector_math_64/aabb3.dart
+++ b/pub/vector_math/lib/src/vector_math_64/aabb3.dart
@@ -86,46 +86,46 @@
   /// Set the AABB to enclose a [triangle].
   void setTriangle(Triangle triangle) {
     _min.setValues(
-        Math.min(triangle._point0.x,
-            Math.min(triangle._point1.x, triangle._point2.x)),
-        Math.min(triangle._point0.y,
-            Math.min(triangle._point1.y, triangle._point2.y)),
-        Math.min(triangle._point0.z,
-            Math.min(triangle._point1.z, triangle._point2.z)));
+        math.min(triangle._point0.x,
+            math.min(triangle._point1.x, triangle._point2.x)),
+        math.min(triangle._point0.y,
+            math.min(triangle._point1.y, triangle._point2.y)),
+        math.min(triangle._point0.z,
+            math.min(triangle._point1.z, triangle._point2.z)));
     _max.setValues(
-        Math.max(triangle._point0.x,
-            Math.max(triangle._point1.x, triangle._point2.x)),
-        Math.max(triangle._point0.y,
-            Math.max(triangle._point1.y, triangle._point2.y)),
-        Math.max(triangle._point0.z,
-            Math.max(triangle._point1.z, triangle._point2.z)));
+        math.max(triangle._point0.x,
+            math.max(triangle._point1.x, triangle._point2.x)),
+        math.max(triangle._point0.y,
+            math.max(triangle._point1.y, triangle._point2.y)),
+        math.max(triangle._point0.z,
+            math.max(triangle._point1.z, triangle._point2.z)));
   }
 
   /// Set the AABB to enclose a [quad].
   void setQuad(Quad quad) {
     _min.setValues(
-        Math.min(quad._point0.x,
-            Math.min(quad._point1.x, Math.min(quad._point2.x, quad._point3.x))),
-        Math.min(quad._point0.y,
-            Math.min(quad._point1.y, Math.min(quad._point2.y, quad._point3.y))),
-        Math.min(
+        math.min(quad._point0.x,
+            math.min(quad._point1.x, math.min(quad._point2.x, quad._point3.x))),
+        math.min(quad._point0.y,
+            math.min(quad._point1.y, math.min(quad._point2.y, quad._point3.y))),
+        math.min(
             quad._point0.z,
-            Math.min(
-                quad._point1.z, Math.min(quad._point2.z, quad._point3.z))));
+            math.min(
+                quad._point1.z, math.min(quad._point2.z, quad._point3.z))));
     _max.setValues(
-        Math.max(quad._point0.x,
-            Math.max(quad._point1.x, Math.max(quad._point2.x, quad._point3.x))),
-        Math.max(quad._point0.y,
-            Math.max(quad._point1.y, Math.max(quad._point2.y, quad._point3.y))),
-        Math.max(
+        math.max(quad._point0.x,
+            math.max(quad._point1.x, math.max(quad._point2.x, quad._point3.x))),
+        math.max(quad._point0.y,
+            math.max(quad._point1.y, math.max(quad._point2.y, quad._point3.y))),
+        math.max(
             quad._point0.z,
-            Math.max(
-                quad._point1.z, Math.max(quad._point2.z, quad._point3.z))));
+            math.max(
+                quad._point1.z, math.max(quad._point2.z, quad._point3.z))));
   }
 
   /// Set the AABB to enclose a [obb].
   void setObb3(Obb3 obb) {
-    final corner = new Vector3.zero();
+    final Vector3 corner = new Vector3.zero();
 
     obb.copyCorner(0, corner);
     _min.setFrom(corner);
@@ -156,23 +156,22 @@
   /// Set the AABB to enclose a limited [ray] (or line segment) that is limited
   /// by [limitMin] and [limitMax].
   void setRay(Ray ray, double limitMin, double limitMax) {
-    ray.copyAt(_min, limitMin);
-    ray.copyAt(_max, limitMax);
+    ray..copyAt(_min, limitMin)..copyAt(_max, limitMax);
 
     if (_max.x < _min.x) {
-      final temp = _max.x;
+      final double temp = _max.x;
       _max.x = _min.x;
       _min.x = temp;
     }
 
     if (_max.y < _min.y) {
-      final temp = _max.y;
+      final double temp = _max.y;
       _max.y = _min.y;
       _min.y = temp;
     }
 
     if (_max.z < _min.z) {
-      final temp = _max.z;
+      final double temp = _max.z;
       _max.z = _min.z;
       _min.z = temp;
     }
@@ -206,8 +205,8 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    final center = new Vector3.zero();
-    final halfExtents = new Vector3.zero();
+    final Vector3 center = new Vector3.zero();
+    final Vector3 halfExtents = new Vector3.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t
       ..transform3(center)
@@ -222,8 +221,8 @@
 
   /// Rotate [this] by the rotation matrix [t].
   void rotate(Matrix4 t) {
-    final center = new Vector3.zero();
-    final halfExtents = new Vector3.zero();
+    final Vector3 center = new Vector3.zero();
+    final Vector3 halfExtents = new Vector3.zero();
     copyCenterAndHalfExtents(center, halfExtents);
     t.absoluteRotate(halfExtents);
     _min
@@ -287,8 +286,8 @@
 
   /// Return if [this] contains [other].
   bool containsAabb3(Aabb3 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector3 otherMax = other._max;
+    final Vector3 otherMin = other._min;
 
     return (_min.x < otherMin.x) &&
         (_min.y < otherMin.y) &&
@@ -300,21 +299,21 @@
 
   /// Return if [this] contains [other].
   bool containsSphere(Sphere other) {
-    final boxExtends = new Vector3.all(other._radius);
-    final sphereBox = new Aabb3.centerAndHalfExtents(other._center, boxExtends);
+    final Vector3 boxExtends = new Vector3.all(other._radius);
+    final Aabb3 sphereBox =
+        new Aabb3.centerAndHalfExtents(other._center, boxExtends);
 
     return containsAabb3(sphereBox);
   }
 
   /// Return if [this] contains [other].
-  bool containsVector3(Vector3 other) {
-    return (_min.x < other.x) &&
-        (_min.y < other.y) &&
-        (_min.z < other.z) &&
-        (_max.x > other.x) &&
-        (_max.y > other.y) &&
-        (_max.z > other.z);
-  }
+  bool containsVector3(Vector3 other) =>
+      (_min.x < other.x) &&
+      (_min.y < other.y) &&
+      (_min.z < other.z) &&
+      (_max.x > other.x) &&
+      (_max.y > other.y) &&
+      (_max.z > other.z);
 
   /// Return if [this] contains [other].
   bool containsTriangle(Triangle other) =>
@@ -324,8 +323,8 @@
 
   /// Return if [this] intersects with [other].
   bool intersectsWithAabb3(Aabb3 other) {
-    final otherMax = other._max;
-    final otherMin = other._min;
+    final Vector3 otherMax = other._max;
+    final Vector3 otherMin = other._min;
 
     return (_min.x <= otherMax.x) &&
         (_min.y <= otherMax.y) &&
@@ -337,12 +336,12 @@
 
   /// Return if [this] intersects with [other].
   bool intersectsWithSphere(Sphere other) {
-    final center = other._center;
-    final radius = other._radius;
-    var d = 0.0;
-    var e = 0.0;
+    final Vector3 center = other._center;
+    final double radius = other._radius;
+    double d = 0.0;
+    double e = 0.0;
 
-    for (var i = 0; i < 3; ++i) {
+    for (int i = 0; i < 3; ++i) {
       if ((e = center[i] - _min[i]) < 0.0) {
         if (e < -radius) {
           return false;
@@ -364,29 +363,28 @@
   }
 
   /// Return if [this] intersects with [other].
-  bool intersectsWithVector3(Vector3 other) {
-    return (_min.x <= other.x) &&
-        (_min.y <= other.y) &&
-        (_min.z <= other.z) &&
-        (_max.x >= other.x) &&
-        (_max.y >= other.y) &&
-        (_max.z >= other.z);
-  }
+  bool intersectsWithVector3(Vector3 other) =>
+      (_min.x <= other.x) &&
+      (_min.y <= other.y) &&
+      (_min.z <= other.z) &&
+      (_max.x >= other.x) &&
+      (_max.y >= other.y) &&
+      (_max.z >= other.z);
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _aabbCenter = new Vector3.zero();
-  static final _aabbHalfExtents = new Vector3.zero();
-  static final _v0 = new Vector3.zero();
-  static final _v1 = new Vector3.zero();
-  static final _v2 = new Vector3.zero();
-  static final _f0 = new Vector3.zero();
-  static final _f1 = new Vector3.zero();
-  static final _f2 = new Vector3.zero();
-  static final _trianglePlane = new Plane();
+  static final Vector3 _aabbCenter = new Vector3.zero();
+  static final Vector3 _aabbHalfExtents = new Vector3.zero();
+  static final Vector3 _v0 = new Vector3.zero();
+  static final Vector3 _v1 = new Vector3.zero();
+  static final Vector3 _v2 = new Vector3.zero();
+  static final Vector3 _f0 = new Vector3.zero();
+  static final Vector3 _f1 = new Vector3.zero();
+  static final Vector3 _f2 = new Vector3.zero();
+  static final Plane _trianglePlane = new Plane();
 
-  static final _u0 = new Vector3(1.0, 0.0, 0.0);
-  static final _u1 = new Vector3(0.0, 1.0, 0.0);
-  static final _u2 = new Vector3(0.0, 0.0, 1.0);
+  static final Vector3 _u0 = new Vector3(1.0, 0.0, 0.0);
+  static final Vector3 _u1 = new Vector3(0.0, 1.0, 0.0);
+  static final Vector3 _u2 = new Vector3(0.0, 0.0, 1.0);
 
   /// Return if [this] intersects with [other].
   /// [epsilon] allows the caller to specify a custum eplsilon value that should
@@ -432,11 +430,11 @@
       p0 = _v0.z * _f0.y - _v0.y * _f0.z;
       p2 = _v2.z * _f0.y - _v2.y * _f0.z;
       r = _aabbHalfExtents[1] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.y.abs();
-      if (Math.max(-Math.max(p0, p2), Math.min(p0, p2)) > r + epsilon) {
+      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p2) - r;
+      a = math.min(p0, p2) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u0.crossInto(_f0, result.axis);
@@ -450,11 +448,11 @@
       p0 = _v0.z * _f1.y - _v0.y * _f1.z;
       p1 = _v1.z * _f1.y - _v1.y * _f1.z;
       r = _aabbHalfExtents[1] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.y.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u0.crossInto(_f1, result.axis);
@@ -468,11 +466,11 @@
       p0 = _v0.z * _f2.y - _v0.y * _f2.z;
       p1 = _v1.z * _f2.y - _v1.y * _f2.z;
       r = _aabbHalfExtents[1] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.y.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u0.crossInto(_f2, result.axis);
@@ -486,11 +484,11 @@
       p0 = _v0.x * _f0.z - _v0.z * _f0.x;
       p2 = _v2.x * _f0.z - _v2.z * _f0.x;
       r = _aabbHalfExtents[0] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.x.abs();
-      if (Math.max(-Math.max(p0, p2), Math.min(p0, p2)) > r + epsilon) {
+      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p2) - r;
+      a = math.min(p0, p2) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u1.crossInto(_f0, result.axis);
@@ -504,11 +502,11 @@
       p0 = _v0.x * _f1.z - _v0.z * _f1.x;
       p1 = _v1.x * _f1.z - _v1.z * _f1.x;
       r = _aabbHalfExtents[0] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u1.crossInto(_f1, result.axis);
@@ -522,11 +520,11 @@
       p0 = _v0.x * _f2.z - _v0.z * _f2.x;
       p1 = _v1.x * _f2.z - _v1.z * _f2.x;
       r = _aabbHalfExtents[0] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u1.crossInto(_f2, result.axis);
@@ -540,11 +538,11 @@
       p0 = _v0.y * _f0.x - _v0.x * _f0.y;
       p2 = _v2.y * _f0.x - _v2.x * _f0.y;
       r = _aabbHalfExtents[0] * _f0.y.abs() + _aabbHalfExtents[1] * _f0.x.abs();
-      if (Math.max(-Math.max(p0, p2), Math.min(p0, p2)) > r + epsilon) {
+      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p2) - r;
+      a = math.min(p0, p2) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u2.crossInto(_f0, result.axis);
@@ -558,11 +556,11 @@
       p0 = _v0.y * _f1.x - _v0.x * _f1.y;
       p1 = _v1.y * _f1.x - _v1.x * _f1.y;
       r = _aabbHalfExtents[0] * _f1.y.abs() + _aabbHalfExtents[1] * _f1.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u2.crossInto(_f1, result.axis);
@@ -576,11 +574,11 @@
       p0 = _v0.y * _f2.x - _v0.x * _f2.y;
       p1 = _v1.y * _f2.x - _v1.x * _f2.y;
       r = _aabbHalfExtents[0] * _f2.y.abs() + _aabbHalfExtents[1] * _f2.x.abs();
-      if (Math.max(-Math.max(p0, p1), Math.min(p0, p1)) > r + epsilon) {
+      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
         return false; // Axis is a separating axis
       }
 
-      a = Math.min(p0, p1) - r;
+      a = math.min(p0, p1) - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         _u2.crossInto(_f2, result.axis);
@@ -589,31 +587,31 @@
 
     // Test the three axes corresponding to the face normals of AABB b (category 1). // Exit if...
     // ... [-e0, e0] and [min(v0.x,v1.x,v2.x), max(v0.x,v1.x,v2.x)] do not overlap
-    if (Math.max(_v0.x, Math.max(_v1.x, _v2.x)) < -_aabbHalfExtents[0] ||
-        Math.min(_v0.x, Math.min(_v1.x, _v2.x)) > _aabbHalfExtents[0]) {
+    if (math.max(_v0.x, math.max(_v1.x, _v2.x)) < -_aabbHalfExtents[0] ||
+        math.min(_v0.x, math.min(_v1.x, _v2.x)) > _aabbHalfExtents[0]) {
       return false;
     }
-    a = Math.min(_v0.x, Math.min(_v1.x, _v2.x)) - _aabbHalfExtents[0];
+    a = math.min(_v0.x, math.min(_v1.x, _v2.x)) - _aabbHalfExtents[0];
     if (result != null && (result._depth == null || result._depth < a)) {
       result._depth = a;
       result.axis.setFrom(_u0);
     }
     // ... [-e1, e1] and [min(v0.y,v1.y,v2.y), max(v0.y,v1.y,v2.y)] do not overlap
-    if (Math.max(_v0.y, Math.max(_v1.y, _v2.y)) < -_aabbHalfExtents[1] ||
-        Math.min(_v0.y, Math.min(_v1.y, _v2.y)) > _aabbHalfExtents[1]) {
+    if (math.max(_v0.y, math.max(_v1.y, _v2.y)) < -_aabbHalfExtents[1] ||
+        math.min(_v0.y, math.min(_v1.y, _v2.y)) > _aabbHalfExtents[1]) {
       return false;
     }
-    a = Math.min(_v0.y, Math.min(_v1.y, _v2.y)) - _aabbHalfExtents[1];
+    a = math.min(_v0.y, math.min(_v1.y, _v2.y)) - _aabbHalfExtents[1];
     if (result != null && (result._depth == null || result._depth < a)) {
       result._depth = a;
       result.axis.setFrom(_u1);
     }
     // ... [-e2, e2] and [min(v0.z,v1.z,v2.z), max(v0.z,v1.z,v2.z)] do not overlap
-    if (Math.max(_v0.z, Math.max(_v1.z, _v2.z)) < -_aabbHalfExtents[2] ||
-        Math.min(_v0.z, Math.min(_v1.z, _v2.z)) > _aabbHalfExtents[2]) {
+    if (math.max(_v0.z, math.max(_v1.z, _v2.z)) < -_aabbHalfExtents[2] ||
+        math.min(_v0.z, math.min(_v1.z, _v2.z)) > _aabbHalfExtents[2]) {
       return false;
     }
-    a = Math.min(_v0.z, Math.min(_v1.z, _v2.z)) - _aabbHalfExtents[2];
+    a = math.min(_v0.z, math.min(_v1.z, _v2.z)) - _aabbHalfExtents[2];
     if (result != null && (result._depth == null || result._depth < a)) {
       result._depth = a;
       result.axis.setFrom(_u2);
@@ -635,14 +633,14 @@
     copyCenterAndHalfExtents(_aabbCenter, _aabbHalfExtents);
 
     // Compute the projection interval radius of b onto L(t) = b.c + t * p.n
-    double r = _aabbHalfExtents[0] * other.normal[0].abs() +
+    final double r = _aabbHalfExtents[0] * other.normal[0].abs() +
         _aabbHalfExtents[1] * other.normal[1].abs() +
         _aabbHalfExtents[2] * other.normal[2].abs();
     // Compute distance of box center from plane
-    double s = other.normal.dot(_aabbCenter) - other.constant;
+    final double s = other.normal.dot(_aabbCenter) - other.constant;
     // Intersection occurs when distance s falls within [-r,+r] interval
     if (s.abs() <= r) {
-      final a = s - r;
+      final double a = s - r;
       if (result != null && (result._depth == null || result._depth < a)) {
         result._depth = a;
         result.axis.setFrom(other.normal);
@@ -654,8 +652,8 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _quadTriangle0 = new Triangle();
-  static final _quadTriangle1 = new Triangle();
+  static final Triangle _quadTriangle0 = new Triangle();
+  static final Triangle _quadTriangle1 = new Triangle();
 
   /// Return if [this] intersects with [other].
   /// [epsilon] allows the caller to specify a custum eplsilon value that should
diff --git a/pub/vector_math/lib/src/vector_math_64/colors.dart b/pub/vector_math/lib/src/vector_math_64/colors.dart
index d9917f6..d02ae4e 100644
--- a/pub/vector_math/lib/src/vector_math_64/colors.dart
+++ b/pub/vector_math/lib/src/vector_math_64/colors.dart
@@ -8,10 +8,10 @@
 /// manipulating colors. In addition to that, some known colors can be accessed
 /// for fast prototyping.
 class Colors {
-  static final _hexStringFullRegex = new RegExp(
+  static final RegExp _hexStringFullRegex = new RegExp(
       r'\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})(?:([0-9a-f]{2}))?',
       caseSensitive: false);
-  static final _hexStringSmallRegex = new RegExp(
+  static final RegExp _hexStringSmallRegex = new RegExp(
       r'\#?([0-9a-f])([0-9a-f])([0-9a-f])(?:([0-9a-f]))?',
       caseSensitive: false);
 
@@ -26,42 +26,42 @@
   /// corresponding color value and store it in [result]. The first group is
   /// treated as the alpha channel if a [value] with four groups is passed.
   static void fromHexString(String value, Vector4 result) {
-    final fullMatch = _hexStringFullRegex.matchAsPrefix(value);
+    final Match fullMatch = _hexStringFullRegex.matchAsPrefix(value);
 
     if (fullMatch != null) {
       if (fullMatch[4] == null) {
-        final r = int.parse(fullMatch[1], radix: 16);
-        final g = int.parse(fullMatch[2], radix: 16);
-        final b = int.parse(fullMatch[3], radix: 16);
+        final int r = int.parse(fullMatch[1], radix: 16);
+        final int g = int.parse(fullMatch[2], radix: 16);
+        final int b = int.parse(fullMatch[3], radix: 16);
 
         fromRgba(r, g, b, 255, result);
         return;
       } else {
-        final a = int.parse(fullMatch[1], radix: 16);
-        final r = int.parse(fullMatch[2], radix: 16);
-        final g = int.parse(fullMatch[3], radix: 16);
-        final b = int.parse(fullMatch[4], radix: 16);
+        final int a = int.parse(fullMatch[1], radix: 16);
+        final int r = int.parse(fullMatch[2], radix: 16);
+        final int g = int.parse(fullMatch[3], radix: 16);
+        final int b = int.parse(fullMatch[4], radix: 16);
 
         fromRgba(r, g, b, a, result);
         return;
       }
     }
 
-    final smallMatch = _hexStringSmallRegex.matchAsPrefix(value);
+    final Match smallMatch = _hexStringSmallRegex.matchAsPrefix(value);
 
     if (smallMatch != null) {
       if (smallMatch[4] == null) {
-        final r = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
-        final g = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
-        final b = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
+        final int r = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
+        final int g = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
+        final int b = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
 
         fromRgba(r, g, b, 255, result);
         return;
       } else {
-        final a = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
-        final r = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
-        final g = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
-        final b = int.parse(smallMatch[4] + smallMatch[4], radix: 16);
+        final int a = int.parse(smallMatch[1] + smallMatch[1], radix: 16);
+        final int r = int.parse(smallMatch[2] + smallMatch[2], radix: 16);
+        final int g = int.parse(smallMatch[3] + smallMatch[3], radix: 16);
+        final int b = int.parse(smallMatch[4] + smallMatch[4], radix: 16);
 
         fromRgba(r, g, b, a, result);
         return;
@@ -77,25 +77,25 @@
   /// (default false).
   static String toHexString(Vector4 input,
       {bool alpha: false, bool short: false}) {
-    final r = (input.r * 0xFF).floor() & 0xFF;
-    final g = (input.g * 0xFF).floor() & 0xFF;
-    final b = (input.b * 0xFF).floor() & 0xFF;
-    final a = (input.a * 0xFF).floor() & 0xFF;
+    final int r = (input.r * 0xFF).floor() & 0xFF;
+    final int g = (input.g * 0xFF).floor() & 0xFF;
+    final int b = (input.b * 0xFF).floor() & 0xFF;
+    final int a = (input.a * 0xFF).floor() & 0xFF;
 
-    final isShort = short &&
+    final bool isShort = short &&
         ((r >> 4) == (r & 0xF)) &&
         ((g >> 4) == (g & 0xF)) &&
         ((b >> 4) == (b & 0xF)) &&
         (!alpha || (a >> 4) == (a & 0xF));
 
     if (isShort) {
-      final rgb = (r & 0xF).toRadixString(16) +
+      final String rgb = (r & 0xF).toRadixString(16) +
           (g & 0xF).toRadixString(16) +
           (b & 0xF).toRadixString(16);
 
       return alpha ? (a & 0xF).toRadixString(16) + rgb : rgb;
     } else {
-      final rgb = r.toRadixString(16).padLeft(2, '0') +
+      final String rgb = r.toRadixString(16).padLeft(2, '0') +
           g.toRadixString(16).padLeft(2, '0') +
           b.toRadixString(16).padLeft(2, '0');
 
@@ -107,16 +107,16 @@
   /// in [result].
   static void alphaBlend(
       Vector4 foreground, Vector4 background, Vector4 result) {
-    final a = foreground.a + (1.0 - foreground.a) * background.a;
-    final factor = 1.0 / a;
+    final double a = foreground.a + (1.0 - foreground.a) * background.a;
+    final double factor = 1.0 / a;
 
-    final r = factor *
+    final double r = factor *
         (foreground.a * foreground.r +
             (1.0 - foreground.a) * background.a * background.r);
-    final g = factor *
+    final double g = factor *
         (foreground.a * foreground.g +
             (1.0 - foreground.a) * background.a * background.g);
-    final b = factor *
+    final double b = factor *
         (foreground.a * foreground.b +
             (1.0 - foreground.a) * background.a * background.b);
 
@@ -125,7 +125,7 @@
 
   /// Convert a [input] color to a gray scaled color and store it in [result].
   static void toGrayscale(Vector4 input, Vector4 result) {
-    final value = 0.21 * input.r + 0.71 * input.g + 0.07 * input.b;
+    final double value = 0.21 * input.r + 0.71 * input.g + 0.07 * input.b;
 
     result
       ..r = value
@@ -139,12 +139,12 @@
   /// the default value is 2.2.
   static void linearToGamma(Vector4 linearColor, Vector4 gammaColor,
       [double gamma = 2.2]) {
-    final exponent = 1.0 / gamma;
+    final double exponent = 1.0 / gamma;
 
     gammaColor
-      ..r = Math.pow(linearColor.r, exponent)
-      ..g = Math.pow(linearColor.g, exponent)
-      ..b = Math.pow(linearColor.b, exponent)
+      ..r = math.pow(linearColor.r, exponent).toDouble()
+      ..g = math.pow(linearColor.g, exponent).toDouble()
+      ..b = math.pow(linearColor.b, exponent).toDouble()
       ..a = linearColor.a;
   }
 
@@ -154,21 +154,21 @@
   static void gammaToLinear(Vector4 gammaColor, Vector4 linearColor,
       [double gamma = 2.2]) {
     linearColor
-      ..r = Math.pow(gammaColor.r, gamma)
-      ..g = Math.pow(gammaColor.g, gamma)
-      ..b = Math.pow(gammaColor.b, gamma)
+      ..r = math.pow(gammaColor.r, gamma).toDouble()
+      ..g = math.pow(gammaColor.g, gamma).toDouble()
+      ..b = math.pow(gammaColor.b, gamma).toDouble()
       ..a = gammaColor.a;
   }
 
   /// Convert [rgbColor] from rgb color model to the hue, saturation, and value
   /// (HSV) color model and store it in [hsvColor].
   static void rgbToHsv(Vector4 rgbColor, Vector4 hsvColor) {
-    final max = Math.max(Math.max(rgbColor.r, rgbColor.g), rgbColor.b);
-    final min = Math.min(Math.min(rgbColor.r, rgbColor.g), rgbColor.b);
-    final d = max - min;
-    final v = max;
-    final s = max == 0.0 ? 0.0 : d / max;
-    var h = 0.0;
+    final double max = math.max(math.max(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double min = math.min(math.min(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double d = max - min;
+    final double v = max;
+    final double s = max == 0.0 ? 0.0 : d / max;
+    double h = 0.0;
 
     if (max != min) {
       if (max == rgbColor.r) {
@@ -189,11 +189,11 @@
   /// Convert [hsvColor] from hue, saturation, and value (HSV) color model to
   /// the RGB color model and store it in [rgbColor].
   static void hsvToRgb(Vector4 hsvColor, Vector4 rgbColor) {
-    final i = (hsvColor.x * 6.0).floor();
-    final f = hsvColor.x * 6.0 - i.toDouble();
-    final p = hsvColor.z * (1.0 - hsvColor.y);
-    final q = hsvColor.z * (1.0 - f * hsvColor.y);
-    final t = hsvColor.z * (1.0 - (1.0 - f) * hsvColor.y);
+    final int i = (hsvColor.x * 6.0).floor();
+    final double f = hsvColor.x * 6.0 - i.toDouble();
+    final double p = hsvColor.z * (1.0 - hsvColor.y);
+    final double q = hsvColor.z * (1.0 - f * hsvColor.y);
+    final double t = hsvColor.z * (1.0 - (1.0 - f) * hsvColor.y);
 
     switch (i % 6) {
       case 0:
@@ -220,14 +220,14 @@
   /// Convert [rgbColor] from rgb color model to the hue, saturation, and
   /// lightness (HSL) color model and store it in [hslColor].
   static void rgbToHsl(Vector4 rgbColor, Vector4 hslColor) {
-    final max = Math.max(Math.max(rgbColor.r, rgbColor.g), rgbColor.b);
-    final min = Math.min(Math.min(rgbColor.r, rgbColor.g), rgbColor.b);
-    final l = (max + min) / 2.0;
-    var h = 0.0;
-    var s = 0.0;
+    final double max = math.max(math.max(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double min = math.min(math.min(rgbColor.r, rgbColor.g), rgbColor.b);
+    final double l = (max + min) / 2.0;
+    double h = 0.0;
+    double s = 0.0;
 
     if (max != min) {
-      final d = max - min;
+      final double d = max - min;
 
       s = l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
 
@@ -252,14 +252,14 @@
     if (hslColor.y == 0.0) {
       rgbColor.setValues(hslColor.z, hslColor.z, hslColor.z, hslColor.a);
     } else {
-      final q = hslColor.z < 0.5
+      final double q = hslColor.z < 0.5
           ? hslColor.z * (1.0 + hslColor.y)
           : hslColor.z + hslColor.y - hslColor.z * hslColor.y;
-      final p = 2.0 * hslColor.z - q;
+      final double p = 2.0 * hslColor.z - q;
 
-      final r = _hueToRgb(p, q, hslColor.x + 1.0 / 3.0);
-      final g = _hueToRgb(p, q, hslColor.x);
-      final b = _hueToRgb(p, q, hslColor.x - 1.0 / 3.0);
+      final double r = _hueToRgb(p, q, hslColor.x + 1.0 / 3.0);
+      final double g = _hueToRgb(p, q, hslColor.x);
+      final double b = _hueToRgb(p, q, hslColor.x - 1.0 / 3.0);
 
       rgbColor.setValues(r, g, b, hslColor.a);
     }
diff --git a/pub/vector_math/lib/src/vector_math_64/constants.dart b/pub/vector_math/lib/src/vector_math_64/constants.dart
index 92114db..32c5fc2 100644
--- a/pub/vector_math/lib/src/vector_math_64/constants.dart
+++ b/pub/vector_math/lib/src/vector_math_64/constants.dart
@@ -5,7 +5,7 @@
 part of vector_math_64;
 
 /// Constant factor to convert and angle from degrees to radians.
-const double degrees2Radians = Math.PI / 180.0;
+const double degrees2Radians = math.PI / 180.0;
 
 /// Constant factor to convert and angle from radians to degrees.
-const double radians2Degrees = 180.0 / Math.PI;
+const double radians2Degrees = 180.0 / math.PI;
diff --git a/pub/vector_math/lib/src/vector_math_64/error_helpers.dart b/pub/vector_math/lib/src/vector_math_64/error_helpers.dart
index 95f87ff..b1a43fa 100644
--- a/pub/vector_math/lib/src/vector_math_64/error_helpers.dart
+++ b/pub/vector_math/lib/src/vector_math_64/error_helpers.dart
@@ -7,21 +7,23 @@
 /// Returns relative error between [calculated] and [correct].
 /// The type of [calculated] and [correct] must match and can
 /// be any vector, matrix, or quaternion.
-double relativeError(calculated, correct) {
+double relativeError(dynamic calculated, dynamic correct) {
   if (calculated is num && correct is num) {
-    double diff = (calculated - correct).abs();
+    final double diff = (calculated - correct).abs().toDouble();
     return diff / correct;
   }
+  // ignore: return_of_invalid_type
   return calculated.relativeError(correct);
 }
 
 /// Returns absolute error between [calculated] and [correct].
 /// The type of [calculated] and [correct] must match and can
 /// be any vector, matrix, or quaternion.
-double absoluteError(calculated, correct) {
+double absoluteError(dynamic calculated, dynamic correct) {
   if (calculated is num && correct is num) {
-    double diff = (calculated - correct).abs();
+    final double diff = (calculated - correct).abs().toDouble();
     return diff;
   }
+  // ignore: return_of_invalid_type
   return calculated.absoluteError(correct);
 }
diff --git a/pub/vector_math/lib/src/vector_math_64/frustum.dart b/pub/vector_math/lib/src/vector_math_64/frustum.dart
index 5f0f9f5..600e1b1 100644
--- a/pub/vector_math/lib/src/vector_math_64/frustum.dart
+++ b/pub/vector_math/lib/src/vector_math_64/frustum.dart
@@ -59,11 +59,11 @@
 
   /// Set [this] from [matrix].
   void setFromMatrix(Matrix4 matrix) {
-    var me = matrix.storage;
-    var me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
-    var me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
-    var me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
-    var me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
+    final Float64List me = matrix.storage;
+    final double me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
+    final double me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
+    final double me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
+    final double me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
 
     _plane0
       ..setFromComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12)
@@ -145,8 +145,8 @@
 
   /// Check if [this] intersects with [sphere].
   bool intersectsWithSphere(Sphere sphere) {
-    final negativeRadius = -sphere._radius;
-    final center = sphere.center;
+    final double negativeRadius = -sphere._radius;
+    final Vector3 center = sphere.center;
 
     if (_plane0.distanceToVector3(center) < negativeRadius) {
       return false;
@@ -197,7 +197,7 @@
   }
 
   bool _intersectsWithAabb3CheckPlane(Aabb3 aabb, Plane plane) {
-    var outPx, outPy, outPz, outNx, outNy, outNz;
+    double outPx, outPy, outPz, outNx, outNy, outNz;
 
     if (plane._normal.x < 0.0) {
       outPx = aabb.min.x;
@@ -223,11 +223,11 @@
       outNz = aabb.min.z;
     }
 
-    final d1 = plane._normal.x * outPx +
+    final double d1 = plane._normal.x * outPx +
         plane._normal.y * outPy +
         plane._normal.z * outPz +
         plane._constant;
-    final d2 = plane._normal.x * outNx +
+    final double d2 = plane._normal.x * outNx +
         plane._normal.y * outNy +
         plane._normal.z * outNz +
         plane._constant;
diff --git a/pub/vector_math/lib/src/vector_math_64/matrix2.dart b/pub/vector_math/lib/src/vector_math_64/matrix2.dart
index 4c87128..5c965d4 100644
--- a/pub/vector_math/lib/src/vector_math_64/matrix2.dart
+++ b/pub/vector_math/lib/src/vector_math_64/matrix2.dart
@@ -26,8 +26,9 @@
       det = 1.0 / det;
     }
 
-    x.x = det * (a22 * bx - a12 * by);
-    x.y = det * (a11 * by - a21 * bx);
+    x
+      ..x = det * (a22 * bx - a12 * by)
+      ..y = det * (a11 * by - a21 * bx);
   }
 
   /// Return index in storage for [row], [col] value.
@@ -42,7 +43,7 @@
   }
 
   /// Set value at [row], [col] to be [v].
-  setEntry(int row, int col, double v) {
+  void setEntry(int row, int col, double v) {
     assert((row >= 0) && (row < dimension));
     assert((col >= 0) && (col < dimension));
 
@@ -54,10 +55,8 @@
       new Matrix2.zero()..setValues(arg0, arg1, arg2, arg3);
 
   /// New matrix from [values].
-  factory Matrix2.fromList(List<double> values) {
-    return new Matrix2.zero()
-      ..setValues(values[0], values[1], values[2], values[3]);
-  }
+  factory Matrix2.fromList(List<double> values) =>
+      new Matrix2.zero()..setValues(values[0], values[1], values[2], values[3]);
 
   /// Zero matrix.
   Matrix2.zero() : _m2storage = new Float64List(4);
@@ -90,8 +89,8 @@
 
   /// Sets the entire matrix to the column values.
   void setColumns(Vector2 arg0, Vector2 arg1) {
-    final arg0Storage = arg0._v2storage;
-    final arg1Storage = arg1._v2storage;
+    final Float64List arg0Storage = arg0._v2storage;
+    final Float64List arg1Storage = arg1._v2storage;
     _m2storage[0] = arg0Storage[0];
     _m2storage[1] = arg0Storage[1];
     _m2storage[2] = arg1Storage[0];
@@ -100,7 +99,7 @@
 
   /// Sets the entire matrix to the matrix in [arg].
   void setFrom(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float64List argStorage = arg._m2storage;
     _m2storage[3] = argStorage[3];
     _m2storage[2] = argStorage[2];
     _m2storage[1] = argStorage[1];
@@ -109,8 +108,8 @@
 
   /// Set [this] to the outer product of [u] and [v].
   void setOuter(Vector2 u, Vector2 v) {
-    final uStorage = u._v2storage;
-    final vStorage = v._v2storage;
+    final Float64List uStorage = u._v2storage;
+    final Float64List vStorage = v._v2storage;
     _m2storage[0] = uStorage[0] * vStorage[0];
     _m2storage[1] = uStorage[0] * vStorage[1];
     _m2storage[2] = uStorage[1] * vStorage[0];
@@ -125,12 +124,13 @@
 
   /// Sets the diagonal of the matrix to be [arg].
   void setDiagonal(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _m2storage[0] = argStorage[0];
     _m2storage[3] = argStorage[1];
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n';
 
   /// Dimension of the matrix.
@@ -145,14 +145,15 @@
   }
 
   /// Check if two matrices are the same.
-  bool operator ==(other) {
-    return (other is Matrix2) &&
-        (_m2storage[0] == other._m2storage[0]) &&
-        (_m2storage[1] == other._m2storage[1]) &&
-        (_m2storage[2] == other._m2storage[2]) &&
-        (_m2storage[3] == other._m2storage[3]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Matrix2) &&
+      (_m2storage[0] == other._m2storage[0]) &&
+      (_m2storage[1] == other._m2storage[1]) &&
+      (_m2storage[2] == other._m2storage[2]) &&
+      (_m2storage[3] == other._m2storage[3]);
 
+  @override
   int get hashCode => quiver.hashObjects(_m2storage);
 
   /// Returns row 0
@@ -169,15 +170,15 @@
 
   /// Sets [row] of the matrix to values in [arg]
   void setRow(int row, Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _m2storage[index(row, 0)] = argStorage[0];
     _m2storage[index(row, 1)] = argStorage[1];
   }
 
   /// Gets the [row] of the matrix
   Vector2 getRow(int row) {
-    final r = new Vector2.zero();
-    final rStorage = r._v2storage;
+    final Vector2 r = new Vector2.zero();
+    final Float64List rStorage = r._v2storage;
     rStorage[0] = _m2storage[index(row, 0)];
     rStorage[1] = _m2storage[index(row, 1)];
     return r;
@@ -185,17 +186,17 @@
 
   /// Assigns the [column] of the matrix [arg]
   void setColumn(int column, Vector2 arg) {
-    final argStorage = arg._v2storage;
-    final entry = column * 2;
+    final Float64List argStorage = arg._v2storage;
+    final int entry = column * 2;
     _m2storage[entry + 1] = argStorage[1];
     _m2storage[entry + 0] = argStorage[0];
   }
 
   /// Gets the [column] of the matrix
   Vector2 getColumn(int column) {
-    final r = new Vector2.zero();
-    final entry = column * 2;
-    final rStorage = r._v2storage;
+    final Vector2 r = new Vector2.zero();
+    final int entry = column * 2;
+    final Float64List rStorage = r._v2storage;
     rStorage[1] = _m2storage[entry + 1];
     rStorage[0] = _m2storage[entry + 0];
     return r;
@@ -206,7 +207,7 @@
 
   /// Copy [this] into [arg].
   Matrix2 copyInto(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float64List argStorage = arg._m2storage;
     argStorage[0] = _m2storage[0];
     argStorage[1] = _m2storage[1];
     argStorage[2] = _m2storage[2];
@@ -215,14 +216,14 @@
   }
 
   /// Returns a new vector or matrix by multiplying [this] with [arg].
-  operator *(dynamic arg) {
+  dynamic operator *(dynamic arg) {
     if (arg is double) {
       return scaled(arg);
     }
     if (arg is Vector2) {
       return transformed(arg);
     }
-    if (arg.dimension == 2) {
+    if (arg is Matrix2) {
       return multiplied(arg);
     }
     throw new ArgumentError(arg);
@@ -257,15 +258,15 @@
   Matrix2 transposed() => clone()..transpose();
 
   void transpose() {
-    double temp = _m2storage[2];
+    final double temp = _m2storage[2];
     _m2storage[2] = _m2storage[1];
     _m2storage[1] = temp;
   }
 
   /// Returns the component wise absolute value of this.
   Matrix2 absolute() {
-    Matrix2 r = new Matrix2.zero();
-    final rStorage = r._m2storage;
+    final Matrix2 r = new Matrix2.zero();
+    final Float64List rStorage = r._m2storage;
     rStorage[0] = _m2storage[0].abs();
     rStorage[1] = _m2storage[1].abs();
     rStorage[2] = _m2storage[2].abs();
@@ -279,13 +280,13 @@
 
   /// Returns the dot product of row [i] and [v].
   double dotRow(int i, Vector2 v) {
-    final vStorage = v._v2storage;
+    final Float64List vStorage = v._v2storage;
     return _m2storage[i] * vStorage[0] + _m2storage[2 + i] * vStorage[1];
   }
 
   /// Returns the dot product of column [j] and [v].
   double dotColumn(int j, Vector2 v) {
-    final vStorage = v._v2storage;
+    final Float64List vStorage = v._v2storage;
     return _m2storage[j * 2] * vStorage[0] +
         _m2storage[(j * 2) + 1] * vStorage[1];
   }
@@ -318,28 +319,28 @@
 
   /// Returns relative error between [this] and [correct]
   double relativeError(Matrix2 correct) {
-    Matrix2 diff = correct - this;
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = diff.infinityNorm();
+    final Matrix2 diff = correct - this;
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = diff.infinityNorm();
     return diff_norm / correct_norm;
   }
 
   /// Returns absolute error between [this] and [correct]
   double absoluteError(Matrix2 correct) {
-    double this_norm = infinityNorm();
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = (this_norm - correct_norm).abs();
+    final double this_norm = infinityNorm();
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = (this_norm - correct_norm).abs();
     return diff_norm;
   }
 
   /// Invert the matrix. Returns the determinant.
   double invert() {
-    double det = determinant();
+    final double det = determinant();
     if (det == 0.0) {
       return 0.0;
     }
-    double invDet = 1.0 / det;
-    double temp = _m2storage[0];
+    final double invDet = 1.0 / det;
+    final double temp = _m2storage[0];
     _m2storage[0] = _m2storage[3] * invDet;
     _m2storage[1] = -_m2storage[1] * invDet;
     _m2storage[2] = -_m2storage[2] * invDet;
@@ -349,13 +350,13 @@
 
   /// Set this matrix to be the inverse of [arg]
   double copyInverse(Matrix2 arg) {
-    double det = arg.determinant();
+    final double det = arg.determinant();
     if (det == 0.0) {
       setFrom(arg);
       return 0.0;
     }
-    double invDet = 1.0 / det;
-    final argStorage = arg._m2storage;
+    final double invDet = 1.0 / det;
+    final Float64List argStorage = arg._m2storage;
     _m2storage[0] = argStorage[3] * invDet;
     _m2storage[1] = -argStorage[1] * invDet;
     _m2storage[2] = -argStorage[2] * invDet;
@@ -365,8 +366,8 @@
 
   /// Turns the matrix into a rotation of [radians]
   void setRotation(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m2storage[0] = c;
     _m2storage[1] = s;
     _m2storage[2] = -s;
@@ -375,7 +376,7 @@
 
   /// Converts into Adjugate matrix and scales by [scale]
   void scaleAdjoint(double scale) {
-    double temp = _m2storage[0];
+    final double temp = _m2storage[0];
     _m2storage[0] = _m2storage[3] * scale;
     _m2storage[2] = -_m2storage[2] * scale;
     _m2storage[1] = -_m2storage[1] * scale;
@@ -395,7 +396,7 @@
 
   /// Add [o] to [this].
   void add(Matrix2 o) {
-    final oStorage = o._m2storage;
+    final Float64List oStorage = o._m2storage;
     _m2storage[0] = _m2storage[0] + oStorage[0];
     _m2storage[1] = _m2storage[1] + oStorage[1];
     _m2storage[2] = _m2storage[2] + oStorage[2];
@@ -404,7 +405,7 @@
 
   /// Subtract [o] from [this].
   void sub(Matrix2 o) {
-    final oStorage = o._m2storage;
+    final Float64List oStorage = o._m2storage;
     _m2storage[0] = _m2storage[0] - oStorage[0];
     _m2storage[1] = _m2storage[1] - oStorage[1];
     _m2storage[2] = _m2storage[2] - oStorage[2];
@@ -421,15 +422,15 @@
 
   /// Multiply [this] with [arg] and store it in [this].
   void multiply(Matrix2 arg) {
-    final m00 = _m2storage[0];
-    final m01 = _m2storage[2];
-    final m10 = _m2storage[1];
-    final m11 = _m2storage[3];
-    final argStorage = arg._m2storage;
-    final n00 = argStorage[0];
-    final n01 = argStorage[2];
-    final n10 = argStorage[1];
-    final n11 = argStorage[3];
+    final double m00 = _m2storage[0];
+    final double m01 = _m2storage[2];
+    final double m10 = _m2storage[1];
+    final double m11 = _m2storage[3];
+    final Float64List argStorage = arg._m2storage;
+    final double n00 = argStorage[0];
+    final double n01 = argStorage[2];
+    final double n10 = argStorage[1];
+    final double n11 = argStorage[3];
     _m2storage[0] = (m00 * n00) + (m01 * n10);
     _m2storage[2] = (m00 * n01) + (m01 * n11);
     _m2storage[1] = (m10 * n00) + (m11 * n10);
@@ -441,11 +442,11 @@
 
   /// Multiply a transposed [this] with [arg].
   void transposeMultiply(Matrix2 arg) {
-    final m00 = _m2storage[0];
-    final m01 = _m2storage[1];
-    final m10 = _m2storage[2];
-    final m11 = _m2storage[3];
-    final argStorage = arg._m2storage;
+    final double m00 = _m2storage[0];
+    final double m01 = _m2storage[1];
+    final double m10 = _m2storage[2];
+    final double m11 = _m2storage[3];
+    final Float64List argStorage = arg._m2storage;
     _m2storage[0] = (m00 * argStorage[0]) + (m01 * argStorage[1]);
     _m2storage[2] = (m00 * argStorage[2]) + (m01 * argStorage[3]);
     _m2storage[1] = (m10 * argStorage[0]) + (m11 * argStorage[1]);
@@ -454,11 +455,11 @@
 
   /// Multiply [this] with a transposed [arg].
   void multiplyTranspose(Matrix2 arg) {
-    final m00 = _m2storage[0];
-    final m01 = _m2storage[2];
-    final m10 = _m2storage[1];
-    final m11 = _m2storage[3];
-    final argStorage = arg._m2storage;
+    final double m00 = _m2storage[0];
+    final double m01 = _m2storage[2];
+    final double m10 = _m2storage[1];
+    final double m11 = _m2storage[3];
+    final Float64List argStorage = arg._m2storage;
     _m2storage[0] = (m00 * argStorage[0]) + (m01 * argStorage[2]);
     _m2storage[2] = (m00 * argStorage[1]) + (m01 * argStorage[3]);
     _m2storage[1] = (m10 * argStorage[0]) + (m11 * argStorage[2]);
@@ -468,9 +469,11 @@
   /// Transform [arg] of type [Vector2] using the transformation defined by
   /// [this].
   Vector2 transform(Vector2 arg) {
-    final argStorage = arg._v2storage;
-    final x = (_m2storage[0] * argStorage[0]) + (_m2storage[2] * argStorage[1]);
-    final y = (_m2storage[1] * argStorage[0]) + (_m2storage[3] * argStorage[1]);
+    final Float64List argStorage = arg._v2storage;
+    final double x =
+        (_m2storage[0] * argStorage[0]) + (_m2storage[2] * argStorage[1]);
+    final double y =
+        (_m2storage[1] * argStorage[0]) + (_m2storage[3] * argStorage[1]);
     argStorage[0] = x;
     argStorage[1] = y;
     return arg;
@@ -490,7 +493,7 @@
 
   /// Copies [this] into [array] starting at [offset].
   void copyIntoArray(List<num> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     array[i + 3] = _m2storage[3];
     array[i + 2] = _m2storage[2];
     array[i + 1] = _m2storage[1];
@@ -499,7 +502,7 @@
 
   /// Copies elements from [array] into [this] starting at [offset].
   void copyFromArray(List<double> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     _m2storage[3] = array[i + 3];
     _m2storage[2] = array[i + 2];
     _m2storage[1] = array[i + 1];
diff --git a/pub/vector_math/lib/src/vector_math_64/matrix3.dart b/pub/vector_math/lib/src/vector_math_64/matrix3.dart
index 2499d9a..f05f164 100644
--- a/pub/vector_math/lib/src/vector_math_64/matrix3.dart
+++ b/pub/vector_math/lib/src/vector_math_64/matrix3.dart
@@ -26,8 +26,9 @@
       det = 1.0 / det;
     }
 
-    x.x = det * (a22 * bx - a12 * by);
-    x.y = det * (a11 * by - a21 * bx);
+    x
+      ..x = det * (a22 * bx - a12 * by)
+      ..y = det * (a11 * by - a21 * bx);
   }
 
   /// Solve [A] * [x] = [b].
@@ -72,9 +73,10 @@
     // Column0 dot -[b cross Column 1]
     final double z_ = det * (A0x * rx + A0y * ry + A0z * rz);
 
-    x.x = x_;
-    x.y = y_;
-    x.z = z_;
+    x
+      ..x = x_
+      ..y = y_
+      ..z = z_;
   }
 
   /// Return index in storage for [row], [col] value.
@@ -89,7 +91,7 @@
   }
 
   /// Set value at [row], [col] to be [v].
-  setEntry(int row, int col, double v) {
+  void setEntry(int row, int col, double v) {
     assert((row >= 0) && (row < dimension));
     assert((col >= 0) && (col < dimension));
 
@@ -103,11 +105,9 @@
         ..setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
 
   /// New matrix from [values].
-  factory Matrix3.fromList(List<double> values) {
-    return new Matrix3.zero()
-      ..setValues(values[0], values[1], values[2], values[3], values[4],
-          values[5], values[6], values[7], values[8]);
-  }
+  factory Matrix3.fromList(List<double> values) => new Matrix3.zero()
+    ..setValues(values[0], values[1], values[2], values[3], values[4],
+        values[5], values[6], values[7], values[8]);
 
   /// Constructs a new [Matrix3] filled with zeros.
   Matrix3.zero() : _m3storage = new Float64List(9);
@@ -154,9 +154,9 @@
 
   /// Sets the entire matrix to the column values.
   void setColumns(Vector3 arg0, Vector3 arg1, Vector3 arg2) {
-    final arg0Storage = arg0._v3storage;
-    final arg1Storage = arg1._v3storage;
-    final arg2Storage = arg2._v3storage;
+    final Float64List arg0Storage = arg0._v3storage;
+    final Float64List arg1Storage = arg1._v3storage;
+    final Float64List arg2Storage = arg2._v3storage;
     _m3storage[0] = arg0Storage[0];
     _m3storage[1] = arg0Storage[1];
     _m3storage[2] = arg0Storage[2];
@@ -170,7 +170,7 @@
 
   /// Sets the entire matrix to the matrix in [arg].
   void setFrom(Matrix3 arg) {
-    final argStorage = arg._m3storage;
+    final Float64List argStorage = arg._m3storage;
     _m3storage[8] = argStorage[8];
     _m3storage[7] = argStorage[7];
     _m3storage[6] = argStorage[6];
@@ -184,8 +184,8 @@
 
   /// Set [this] to the outer product of [u] and [v].
   void setOuter(Vector3 u, Vector3 v) {
-    final uStorage = u._v3storage;
-    final vStorage = v._v3storage;
+    final Float64List uStorage = u._v3storage;
+    final Float64List vStorage = v._v3storage;
     _m3storage[0] = uStorage[0] * vStorage[0];
     _m3storage[1] = uStorage[0] * vStorage[1];
     _m3storage[2] = uStorage[0] * vStorage[2];
@@ -213,7 +213,7 @@
 
   /// Sets the upper 2x2 of the matrix to be [arg].
   void setUpper2x2(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float64List argStorage = arg._m2storage;
     _m3storage[0] = argStorage[0];
     _m3storage[1] = argStorage[1];
     _m3storage[3] = argStorage[2];
@@ -221,6 +221,7 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n[2] ${getRow(2)}\n';
 
   /// Dimension of the matrix.
@@ -235,19 +236,20 @@
   }
 
   /// Check if two matrices are the same.
-  bool operator ==(other) {
-    return (other is Matrix3) &&
-        (_m3storage[0] == other._m3storage[0]) &&
-        (_m3storage[1] == other._m3storage[1]) &&
-        (_m3storage[2] == other._m3storage[2]) &&
-        (_m3storage[3] == other._m3storage[3]) &&
-        (_m3storage[4] == other._m3storage[4]) &&
-        (_m3storage[5] == other._m3storage[5]) &&
-        (_m3storage[6] == other._m3storage[6]) &&
-        (_m3storage[7] == other._m3storage[7]) &&
-        (_m3storage[8] == other._m3storage[8]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Matrix3) &&
+      (_m3storage[0] == other._m3storage[0]) &&
+      (_m3storage[1] == other._m3storage[1]) &&
+      (_m3storage[2] == other._m3storage[2]) &&
+      (_m3storage[3] == other._m3storage[3]) &&
+      (_m3storage[4] == other._m3storage[4]) &&
+      (_m3storage[5] == other._m3storage[5]) &&
+      (_m3storage[6] == other._m3storage[6]) &&
+      (_m3storage[7] == other._m3storage[7]) &&
+      (_m3storage[8] == other._m3storage[8]);
 
+  @override
   int get hashCode => quiver.hashObjects(_m3storage);
 
   /// Returns row 0
@@ -270,7 +272,7 @@
 
   /// Assigns the [row] of to [arg].
   void setRow(int row, Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _m3storage[index(row, 0)] = argStorage[0];
     _m3storage[index(row, 1)] = argStorage[1];
     _m3storage[index(row, 2)] = argStorage[2];
@@ -278,8 +280,8 @@
 
   /// Gets the [row] of the matrix
   Vector3 getRow(int row) {
-    Vector3 r = new Vector3.zero();
-    final rStorage = r._v3storage;
+    final Vector3 r = new Vector3.zero();
+    final Float64List rStorage = r._v3storage;
     rStorage[0] = _m3storage[index(row, 0)];
     rStorage[1] = _m3storage[index(row, 1)];
     rStorage[2] = _m3storage[index(row, 2)];
@@ -288,8 +290,8 @@
 
   /// Assigns the [column] of the matrix [arg]
   void setColumn(int column, Vector3 arg) {
-    final argStorage = arg._v3storage;
-    int entry = column * 3;
+    final Float64List argStorage = arg._v3storage;
+    final int entry = column * 3;
     _m3storage[entry + 2] = argStorage[2];
     _m3storage[entry + 1] = argStorage[1];
     _m3storage[entry + 0] = argStorage[0];
@@ -297,9 +299,9 @@
 
   /// Gets the [column] of the matrix
   Vector3 getColumn(int column) {
-    Vector3 r = new Vector3.zero();
-    final rStorage = r._v3storage;
-    int entry = column * 3;
+    final Vector3 r = new Vector3.zero();
+    final Float64List rStorage = r._v3storage;
+    final int entry = column * 3;
     rStorage[2] = _m3storage[entry + 2];
     rStorage[1] = _m3storage[entry + 1];
     rStorage[0] = _m3storage[entry + 0];
@@ -311,7 +313,7 @@
 
   /// Copy [this] into [arg].
   Matrix3 copyInto(Matrix3 arg) {
-    final argStorage = arg._m3storage;
+    final Float64List argStorage = arg._m3storage;
     argStorage[0] = _m3storage[0];
     argStorage[1] = _m3storage[1];
     argStorage[2] = _m3storage[2];
@@ -325,14 +327,14 @@
   }
 
   /// Returns a new vector or matrix by multiplying [this] with [arg].
-  operator *(dynamic arg) {
+  dynamic operator *(dynamic arg) {
     if (arg is double) {
       return scaled(arg);
     }
     if (arg is Vector3) {
       return transformed(arg);
     }
-    if (arg.dimension == 3) {
+    if (arg is Matrix3) {
       return multiplied(arg);
     }
     throw new ArgumentError(arg);
@@ -392,8 +394,8 @@
 
   /// Returns the component wise absolute value of this.
   Matrix3 absolute() {
-    Matrix3 r = new Matrix3.zero();
-    final rStorage = r._m3storage;
+    final Matrix3 r = new Matrix3.zero();
+    final Float64List rStorage = r._m3storage;
     rStorage[0] = _m3storage[0].abs();
     rStorage[1] = _m3storage[1].abs();
     rStorage[2] = _m3storage[2].abs();
@@ -408,18 +410,18 @@
 
   /// Returns the determinant of this matrix.
   double determinant() {
-    double x = _m3storage[0] *
+    final double x = _m3storage[0] *
         ((storage[4] * _m3storage[8]) - (storage[5] * _m3storage[7]));
-    double y = _m3storage[1] *
+    final double y = _m3storage[1] *
         ((storage[3] * _m3storage[8]) - (storage[5] * _m3storage[6]));
-    double z = _m3storage[2] *
+    final double z = _m3storage[2] *
         ((storage[3] * _m3storage[7]) - (storage[4] * _m3storage[6]));
     return x - y + z;
   }
 
   /// Returns the dot product of row [i] and [v].
   double dotRow(int i, Vector3 v) {
-    final vStorage = v._v3storage;
+    final Float64List vStorage = v._v3storage;
     return _m3storage[i] * vStorage[0] +
         _m3storage[3 + i] * vStorage[1] +
         _m3storage[6 + i] * vStorage[2];
@@ -427,7 +429,7 @@
 
   /// Returns the dot product of column [j] and [v].
   double dotColumn(int j, Vector3 v) {
-    final vStorage = v._v3storage;
+    final Float64List vStorage = v._v3storage;
     return _m3storage[j * 3] * vStorage[0] +
         _m3storage[j * 3 + 1] * vStorage[1] +
         _m3storage[j * 3 + 2] * vStorage[2];
@@ -472,17 +474,17 @@
 
   /// Returns relative error between [this] and [correct]
   double relativeError(Matrix3 correct) {
-    Matrix3 diff = correct - this;
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = diff.infinityNorm();
+    final Matrix3 diff = correct - this;
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = diff.infinityNorm();
     return diff_norm / correct_norm;
   }
 
   /// Returns absolute error between [this] and [correct]
   double absoluteError(Matrix3 correct) {
-    double this_norm = infinityNorm();
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = (this_norm - correct_norm).abs();
+    final double this_norm = infinityNorm();
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = (this_norm - correct_norm).abs();
     return diff_norm;
   }
 
@@ -491,30 +493,30 @@
 
   /// Set this matrix to be the inverse of [arg]
   double copyInverse(Matrix3 arg) {
-    final det = arg.determinant();
+    final double det = arg.determinant();
     if (det == 0.0) {
       setFrom(arg);
       return 0.0;
     }
-    final invDet = 1.0 / det;
-    final argStorage = arg._m3storage;
-    final ix = invDet *
+    final double invDet = 1.0 / det;
+    final Float64List argStorage = arg._m3storage;
+    final double ix = invDet *
         (argStorage[4] * argStorage[8] - argStorage[5] * argStorage[7]);
-    final iy = invDet *
+    final double iy = invDet *
         (argStorage[2] * argStorage[7] - argStorage[1] * argStorage[8]);
-    final iz = invDet *
+    final double iz = invDet *
         (argStorage[1] * argStorage[5] - argStorage[2] * argStorage[4]);
-    final jx = invDet *
+    final double jx = invDet *
         (argStorage[5] * argStorage[6] - argStorage[3] * argStorage[8]);
-    final jy = invDet *
+    final double jy = invDet *
         (argStorage[0] * argStorage[8] - argStorage[2] * argStorage[6]);
-    final jz = invDet *
+    final double jz = invDet *
         (argStorage[2] * argStorage[3] - argStorage[0] * argStorage[5]);
-    final kx = invDet *
+    final double kx = invDet *
         (argStorage[3] * argStorage[7] - argStorage[4] * argStorage[6]);
-    final ky = invDet *
+    final double ky = invDet *
         (argStorage[1] * argStorage[6] - argStorage[0] * argStorage[7]);
-    final kz = invDet *
+    final double kz = invDet *
         (argStorage[0] * argStorage[4] - argStorage[1] * argStorage[3]);
     _m3storage[0] = ix;
     _m3storage[1] = iy;
@@ -536,8 +538,8 @@
 
   /// Turns the matrix into a rotation of [radians] around X
   void setRotationX(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m3storage[0] = 1.0;
     _m3storage[1] = 0.0;
     _m3storage[2] = 0.0;
@@ -551,8 +553,8 @@
 
   /// Turns the matrix into a rotation of [radians] around Y
   void setRotationY(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m3storage[0] = c;
     _m3storage[1] = 0.0;
     _m3storage[2] = s;
@@ -566,8 +568,8 @@
 
   /// Turns the matrix into a rotation of [radians] around Z
   void setRotationZ(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m3storage[0] = c;
     _m3storage[1] = s;
     _m3storage[2] = 0.0;
@@ -581,15 +583,15 @@
 
   /// Converts into Adjugate matrix and scales by [scale]
   void scaleAdjoint(double scale) {
-    double m00 = _m3storage[0];
-    double m01 = _m3storage[3];
-    double m02 = _m3storage[6];
-    double m10 = _m3storage[1];
-    double m11 = _m3storage[4];
-    double m12 = _m3storage[7];
-    double m20 = _m3storage[2];
-    double m21 = _m3storage[5];
-    double m22 = _m3storage[8];
+    final double m00 = _m3storage[0];
+    final double m01 = _m3storage[3];
+    final double m02 = _m3storage[6];
+    final double m10 = _m3storage[1];
+    final double m11 = _m3storage[4];
+    final double m12 = _m3storage[7];
+    final double m20 = _m3storage[2];
+    final double m21 = _m3storage[5];
+    final double m22 = _m3storage[8];
     _m3storage[0] = (m11 * m22 - m12 * m21) * scale;
     _m3storage[1] = (m12 * m20 - m10 * m22) * scale;
     _m3storage[2] = (m10 * m21 - m11 * m20) * scale;
@@ -605,19 +607,19 @@
   /// Returns [arg].
   /// Primarily used by AABB transformation code.
   Vector3 absoluteRotate(Vector3 arg) {
-    double m00 = _m3storage[0].abs();
-    double m01 = _m3storage[3].abs();
-    double m02 = _m3storage[6].abs();
-    double m10 = _m3storage[1].abs();
-    double m11 = _m3storage[4].abs();
-    double m12 = _m3storage[7].abs();
-    double m20 = _m3storage[2].abs();
-    double m21 = _m3storage[5].abs();
-    double m22 = _m3storage[8].abs();
-    final argStorage = arg._v3storage;
-    final x = argStorage[0];
-    final y = argStorage[1];
-    final z = argStorage[2];
+    final double m00 = _m3storage[0].abs();
+    final double m01 = _m3storage[3].abs();
+    final double m02 = _m3storage[6].abs();
+    final double m10 = _m3storage[1].abs();
+    final double m11 = _m3storage[4].abs();
+    final double m12 = _m3storage[7].abs();
+    final double m20 = _m3storage[2].abs();
+    final double m21 = _m3storage[5].abs();
+    final double m22 = _m3storage[8].abs();
+    final Float64List argStorage = arg._v3storage;
+    final double x = argStorage[0];
+    final double y = argStorage[1];
+    final double z = argStorage[2];
     argStorage[0] = x * m00 + y * m01 + z * m02;
     argStorage[1] = x * m10 + y * m11 + z * m12;
     argStorage[2] = x * m20 + y * m21 + z * m22;
@@ -628,13 +630,13 @@
   /// Returns [arg].
   /// Primarily used by AABB transformation code.
   Vector2 absoluteRotate2(Vector2 arg) {
-    double m00 = _m3storage[0].abs();
-    double m01 = _m3storage[3].abs();
-    double m10 = _m3storage[1].abs();
-    double m11 = _m3storage[4].abs();
-    final argStorage = arg._v2storage;
-    final x = argStorage[0];
-    final y = argStorage[1];
+    final double m00 = _m3storage[0].abs();
+    final double m01 = _m3storage[3].abs();
+    final double m10 = _m3storage[1].abs();
+    final double m11 = _m3storage[4].abs();
+    final Float64List argStorage = arg._v2storage;
+    final double x = argStorage[0];
+    final double y = argStorage[1];
     argStorage[0] = x * m00 + y * m01;
     argStorage[1] = x * m10 + y * m11;
     return arg;
@@ -642,11 +644,11 @@
 
   /// Transforms [arg] with [this].
   Vector2 transform2(Vector2 arg) {
-    final argStorage = arg._v2storage;
-    double x_ = (storage[0] * arg.storage[0]) +
+    final Float64List argStorage = arg._v2storage;
+    final double x_ = (storage[0] * arg.storage[0]) +
         (storage[3] * arg.storage[1]) +
         _m3storage[6];
-    double y_ = (storage[1] * arg.storage[0]) +
+    final double y_ = (storage[1] * arg.storage[0]) +
         (storage[4] * arg.storage[1]) +
         _m3storage[7];
     argStorage[0] = x_;
@@ -672,7 +674,7 @@
 
   /// Add [o] to [this].
   void add(Matrix3 o) {
-    final oStorage = o._m3storage;
+    final Float64List oStorage = o._m3storage;
     _m3storage[0] = _m3storage[0] + oStorage[0];
     _m3storage[1] = _m3storage[1] + oStorage[1];
     _m3storage[2] = _m3storage[2] + oStorage[2];
@@ -686,7 +688,7 @@
 
   /// Subtract [o] from [this].
   void sub(Matrix3 o) {
-    final oStorage = o._m3storage;
+    final Float64List oStorage = o._m3storage;
     _m3storage[0] = _m3storage[0] - oStorage[0];
     _m3storage[1] = _m3storage[1] - oStorage[1];
     _m3storage[2] = _m3storage[2] - oStorage[2];
@@ -722,7 +724,7 @@
     final double m20 = _m3storage[2];
     final double m21 = _m3storage[5];
     final double m22 = _m3storage[8];
-    final argStorage = arg._m3storage;
+    final Float64List argStorage = arg._m3storage;
     final double n00 = argStorage[0];
     final double n01 = argStorage[3];
     final double n02 = argStorage[6];
@@ -747,16 +749,16 @@
   Matrix3 multiplied(Matrix3 arg) => clone()..multiply(arg);
 
   void transposeMultiply(Matrix3 arg) {
-    double m00 = _m3storage[0];
-    double m01 = _m3storage[1];
-    double m02 = _m3storage[2];
-    double m10 = _m3storage[3];
-    double m11 = _m3storage[4];
-    double m12 = _m3storage[5];
-    double m20 = _m3storage[6];
-    double m21 = _m3storage[7];
-    double m22 = _m3storage[8];
-    final argStorage = arg._m3storage;
+    final double m00 = _m3storage[0];
+    final double m01 = _m3storage[1];
+    final double m02 = _m3storage[2];
+    final double m10 = _m3storage[3];
+    final double m11 = _m3storage[4];
+    final double m12 = _m3storage[5];
+    final double m20 = _m3storage[6];
+    final double m21 = _m3storage[7];
+    final double m22 = _m3storage[8];
+    final Float64List argStorage = arg._m3storage;
     _m3storage[0] =
         (m00 * argStorage[0]) + (m01 * arg.storage[1]) + (m02 * arg.storage[2]);
     _m3storage[3] =
@@ -778,16 +780,16 @@
   }
 
   void multiplyTranspose(Matrix3 arg) {
-    double m00 = _m3storage[0];
-    double m01 = _m3storage[3];
-    double m02 = _m3storage[6];
-    double m10 = _m3storage[1];
-    double m11 = _m3storage[4];
-    double m12 = _m3storage[7];
-    double m20 = _m3storage[2];
-    double m21 = _m3storage[5];
-    double m22 = _m3storage[8];
-    final argStorage = arg._m3storage;
+    final double m00 = _m3storage[0];
+    final double m01 = _m3storage[3];
+    final double m02 = _m3storage[6];
+    final double m10 = _m3storage[1];
+    final double m11 = _m3storage[4];
+    final double m12 = _m3storage[7];
+    final double m20 = _m3storage[2];
+    final double m21 = _m3storage[5];
+    final double m22 = _m3storage[8];
+    final Float64List argStorage = arg._m3storage;
     _m3storage[0] =
         (m00 * argStorage[0]) + (m01 * argStorage[3]) + (m02 * argStorage[6]);
     _m3storage[3] =
@@ -811,19 +813,20 @@
   /// Transform [arg] of type [Vector3] using the transformation defined by
   /// [this].
   Vector3 transform(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    double x_ = (storage[0] * argStorage[0]) +
+    final Float64List argStorage = arg._v3storage;
+    final double x_ = (storage[0] * argStorage[0]) +
         (storage[3] * argStorage[1]) +
         (storage[6] * argStorage[2]);
-    double y_ = (storage[1] * argStorage[0]) +
+    final double y_ = (storage[1] * argStorage[0]) +
         (storage[4] * argStorage[1]) +
         (storage[7] * argStorage[2]);
-    double z_ = (storage[2] * argStorage[0]) +
+    final double z_ = (storage[2] * argStorage[0]) +
         (storage[5] * argStorage[1]) +
         (storage[8] * argStorage[2]);
-    arg.x = x_;
-    arg.y = y_;
-    arg.z = z_;
+    arg
+      ..x = x_
+      ..y = y_
+      ..z = z_;
     return arg;
   }
 
@@ -841,7 +844,7 @@
 
   /// Copies [this] into [array] starting at [offset].
   void copyIntoArray(List<num> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     array[i + 8] = _m3storage[8];
     array[i + 7] = _m3storage[7];
     array[i + 6] = _m3storage[6];
@@ -855,7 +858,7 @@
 
   /// Copies elements from [array] into [this] starting at [offset].
   void copyFromArray(List<double> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     _m3storage[8] = array[i + 8];
     _m3storage[7] = array[i + 7];
     _m3storage[6] = array[i + 6];
@@ -869,8 +872,8 @@
 
   /// Multiply [this] to each set of xyz values in [array] starting at [offset].
   List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
-    for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
-      final v = new Vector3.array(array, j)..applyMatrix3(this);
+    for (int i = 0, j = offset; i < array.length; i += 3, j += 3) {
+      final Vector3 v = new Vector3.array(array, j)..applyMatrix3(this);
       array[j] = v.storage[0];
       array[j + 1] = v.storage[1];
       array[j + 2] = v.storage[2];
@@ -880,49 +883,53 @@
   }
 
   Vector3 get right {
-    double x = _m3storage[0];
-    double y = _m3storage[1];
-    double z = _m3storage[2];
+    final double x = _m3storage[0];
+    final double y = _m3storage[1];
+    final double z = _m3storage[2];
     return new Vector3(x, y, z);
   }
 
   Vector3 get up {
-    double x = _m3storage[3];
-    double y = _m3storage[4];
-    double z = _m3storage[5];
+    final double x = _m3storage[3];
+    final double y = _m3storage[4];
+    final double z = _m3storage[5];
     return new Vector3(x, y, z);
   }
 
   Vector3 get forward {
-    double x = _m3storage[6];
-    double y = _m3storage[7];
-    double z = _m3storage[8];
+    final double x = _m3storage[6];
+    final double y = _m3storage[7];
+    final double z = _m3storage[8];
     return new Vector3(x, y, z);
   }
 
   /// Is [this] the identity matrix?
-  bool isIdentity() {
-    return _m3storage[0] == 1.0 // col 1
-        && _m3storage[1] == 0.0
-        && _m3storage[2] == 0.0
-        && _m3storage[3] == 0.0 // col 2
-        && _m3storage[4] == 1.0
-        && _m3storage[5] == 0.0
-        && _m3storage[6] == 0.0 // col 3
-        && _m3storage[7] == 0.0
-        && _m3storage[8] == 1.0;
-  }
+  bool isIdentity() =>
+      _m3storage[0] == 1.0 // col 1
+      &&
+      _m3storage[1] == 0.0 &&
+      _m3storage[2] == 0.0 &&
+      _m3storage[3] == 0.0 // col 2
+      &&
+      _m3storage[4] == 1.0 &&
+      _m3storage[5] == 0.0 &&
+      _m3storage[6] == 0.0 // col 3
+      &&
+      _m3storage[7] == 0.0 &&
+      _m3storage[8] == 1.0;
 
   /// Is [this] the zero matrix?
-  bool isZero() {
-    return _m3storage[0] == 0.0 // col 1
-        && _m3storage[1] == 0.0
-        && _m3storage[2] == 0.0
-        && _m3storage[3] == 0.0 // col 2
-        && _m3storage[4] == 0.0
-        && _m3storage[5] == 0.0
-        && _m3storage[6] == 0.0 // col 3
-        && _m3storage[7] == 0.0
-        && _m3storage[8] == 0.0;
-  }
+  bool isZero() =>
+      _m3storage[0] == 0.0 // col 1
+      &&
+      _m3storage[1] == 0.0 &&
+      _m3storage[2] == 0.0 &&
+      _m3storage[3] == 0.0 // col 2
+      &&
+      _m3storage[4] == 0.0 &&
+      _m3storage[5] == 0.0 &&
+      _m3storage[6] == 0.0 // col 3
+      &&
+      _m3storage[7] == 0.0 &&
+      _m3storage[8] == 0.0;
 }
diff --git a/pub/vector_math/lib/src/vector_math_64/matrix4.dart b/pub/vector_math/lib/src/vector_math_64/matrix4.dart
index 96e260e..5878c1a 100644
--- a/pub/vector_math/lib/src/vector_math_64/matrix4.dart
+++ b/pub/vector_math/lib/src/vector_math_64/matrix4.dart
@@ -26,8 +26,9 @@
       det = 1.0 / det;
     }
 
-    x.x = det * (a22 * bx - a12 * by);
-    x.y = det * (a11 * by - a21 * bx);
+    x
+      ..x = det * (a22 * bx - a12 * by)
+      ..y = det * (a11 * by - a21 * bx);
   }
 
   /// Solve [A] * [x] = [b].
@@ -75,9 +76,10 @@
     // Column0 dot -[b cross Column 1]
     final double z_ = det * (A0x * rx + A0y * ry + A0z * rz);
 
-    x.x = x_;
-    x.y = y_;
-    x.z = z_;
+    x
+      ..x = x_
+      ..y = y_
+      ..z = z_;
   }
 
   /// Solve [A] * [x] = [b].
@@ -123,29 +125,27 @@
       det = 1.0 / det;
     }
 
-    x.x = det *
-        ((a11 * b11 - a12 * b10 + a13 * b09) * bX -
-            (a10 * b11 - a12 * b08 + a13 * b07) * bY +
-            (a10 * b10 - a11 * b08 + a13 * b06) * bZ -
-            (a10 * b09 - a11 * b07 + a12 * b06) * bW);
-
-    x.y = det *
-        -((a01 * b11 - a02 * b10 + a03 * b09) * bX -
-            (a00 * b11 - a02 * b08 + a03 * b07) * bY +
-            (a00 * b10 - a01 * b08 + a03 * b06) * bZ -
-            (a00 * b09 - a01 * b07 + a02 * b06) * bW);
-
-    x.z = det *
-        ((a31 * b05 - a32 * b04 + a33 * b03) * bX -
-            (a30 * b05 - a32 * b02 + a33 * b01) * bY +
-            (a30 * b04 - a31 * b02 + a33 * b00) * bZ -
-            (a30 * b03 - a31 * b01 + a32 * b00) * bW);
-
-    x.w = det *
-        -((a21 * b05 - a22 * b04 + a23 * b03) * bX -
-            (a20 * b05 - a22 * b02 + a23 * b01) * bY +
-            (a20 * b04 - a21 * b02 + a23 * b00) * bZ -
-            (a20 * b03 - a21 * b01 + a22 * b00) * bW);
+    x
+      ..x = det *
+          ((a11 * b11 - a12 * b10 + a13 * b09) * bX -
+              (a10 * b11 - a12 * b08 + a13 * b07) * bY +
+              (a10 * b10 - a11 * b08 + a13 * b06) * bZ -
+              (a10 * b09 - a11 * b07 + a12 * b06) * bW)
+      ..y = det *
+          -((a01 * b11 - a02 * b10 + a03 * b09) * bX -
+              (a00 * b11 - a02 * b08 + a03 * b07) * bY +
+              (a00 * b10 - a01 * b08 + a03 * b06) * bZ -
+              (a00 * b09 - a01 * b07 + a02 * b06) * bW)
+      ..z = det *
+          ((a31 * b05 - a32 * b04 + a33 * b03) * bX -
+              (a30 * b05 - a32 * b02 + a33 * b01) * bY +
+              (a30 * b04 - a31 * b02 + a33 * b00) * bZ -
+              (a30 * b03 - a31 * b01 + a32 * b00) * bW)
+      ..w = det *
+          -((a21 * b05 - a22 * b04 + a23 * b03) * bX -
+              (a20 * b05 - a22 * b02 + a23 * b01) * bY +
+              (a20 * b04 - a21 * b02 + a23 * b00) * bZ -
+              (a20 * b03 - a21 * b01 + a22 * b00) * bW);
   }
 
   /// Return index in storage for [row], [col] value.
@@ -160,7 +160,7 @@
   }
 
   /// Set value at [row], [col] to be [v].
-  setEntry(int row, int col, double v) {
+  void setEntry(int row, int col, double v) {
     assert((row >= 0) && (row < dimension));
     assert((col >= 0) && (col < dimension));
 
@@ -190,26 +190,24 @@
             arg10, arg11, arg12, arg13, arg14, arg15);
 
   /// New matrix from [values].
-  factory Matrix4.fromList(List<double> values) {
-    return new Matrix4.zero()
-      ..setValues(
-          values[0],
-          values[1],
-          values[2],
-          values[3],
-          values[4],
-          values[5],
-          values[6],
-          values[7],
-          values[8],
-          values[9],
-          values[10],
-          values[11],
-          values[12],
-          values[13],
-          values[14],
-          values[15]);
-  }
+  factory Matrix4.fromList(List<double> values) => new Matrix4.zero()
+    ..setValues(
+        values[0],
+        values[1],
+        values[2],
+        values[3],
+        values[4],
+        values[5],
+        values[6],
+        values[7],
+        values[8],
+        values[9],
+        values[10],
+        values[11],
+        values[12],
+        values[13],
+        values[14],
+        values[15]);
 
   /// Zero matrix.
   Matrix4.zero() : _m4storage = new Float64List(16);
@@ -222,8 +220,8 @@
 
   /// Constructs a matrix that is the inverse of [other].
   factory Matrix4.inverted(Matrix4 other) {
-    Matrix4 r = new Matrix4.zero();
-    double determinant = r.copyInverse(other);
+    final Matrix4 r = new Matrix4.zero();
+    final double determinant = r.copyInverse(other);
     if (determinant == 0.0) {
       throw new ArgumentError.value(
           other, 'other', 'Matrix cannot be inverted');
@@ -268,9 +266,9 @@
 
   /// Scale matrix.
   factory Matrix4.diagonal3(Vector3 scale) {
-    final m = new Matrix4.zero();
-    final mStorage = m._m4storage;
-    final scaleStorage = scale._v3storage;
+    final Matrix4 m = new Matrix4.zero();
+    final Float64List mStorage = m._m4storage;
+    final Float64List scaleStorage = scale._v3storage;
     mStorage[15] = 1.0;
     mStorage[10] = scaleStorage[2];
     mStorage[5] = scaleStorage[1];
@@ -288,27 +286,26 @@
 
   /// Skew matrix around X axis
   factory Matrix4.skewX(double alpha) {
-    final m = new Matrix4.identity();
-    m._m4storage[4] = Math.tan(alpha);
+    final Matrix4 m = new Matrix4.identity();
+    m._m4storage[4] = math.tan(alpha);
     return m;
   }
 
   /// Skew matrix around Y axis.
   factory Matrix4.skewY(double beta) {
-    final m = new Matrix4.identity();
-    m._m4storage[1] = Math.tan(beta);
+    final Matrix4 m = new Matrix4.identity();
+    m._m4storage[1] = math.tan(beta);
     return m;
   }
 
   /// Skew matrix around X axis (alpha) and Y axis (beta).
   factory Matrix4.skew(double alpha, double beta) {
-    final m = new Matrix4.identity();
-    m._m4storage[1] = Math.tan(beta);
-    m._m4storage[4] = Math.tan(alpha);
+    final Matrix4 m = new Matrix4.identity();
+    m._m4storage[1] = math.tan(beta);
+    m._m4storage[4] = math.tan(alpha);
     return m;
   }
 
-
   /// Constructs Matrix4 with given [Float64List] as [storage].
   Matrix4.fromFloat64List(this._m4storage);
 
@@ -369,10 +366,10 @@
 
   /// Sets the entire matrix to the column values.
   void setColumns(Vector4 arg0, Vector4 arg1, Vector4 arg2, Vector4 arg3) {
-    final arg0Storage = arg0._v4storage;
-    final arg1Storage = arg1._v4storage;
-    final arg2Storage = arg2._v4storage;
-    final arg3Storage = arg3._v4storage;
+    final Float64List arg0Storage = arg0._v4storage;
+    final Float64List arg1Storage = arg1._v4storage;
+    final Float64List arg2Storage = arg2._v4storage;
+    final Float64List arg3Storage = arg3._v4storage;
     _m4storage[0] = arg0Storage[0];
     _m4storage[1] = arg0Storage[1];
     _m4storage[2] = arg0Storage[2];
@@ -393,7 +390,7 @@
 
   /// Sets the entire matrix to the matrix in [arg].
   void setFrom(Matrix4 arg) {
-    final argStorage = arg._m4storage;
+    final Float64List argStorage = arg._m4storage;
     _m4storage[15] = argStorage[15];
     _m4storage[14] = argStorage[14];
     _m4storage[13] = argStorage[13];
@@ -414,25 +411,25 @@
 
   /// Sets the matrix from translation [arg0] and rotation [arg1].
   void setFromTranslationRotation(Vector3 arg0, Quaternion arg1) {
-    final arg1Storage = arg1._qStorage;
-    double x = arg1Storage[0];
-    double y = arg1Storage[1];
-    double z = arg1Storage[2];
-    double w = arg1Storage[3];
-    double x2 = x + x;
-    double y2 = y + y;
-    double z2 = z + z;
-    double xx = x * x2;
-    double xy = x * y2;
-    double xz = x * z2;
-    double yy = y * y2;
-    double yz = y * z2;
-    double zz = z * z2;
-    double wx = w * x2;
-    double wy = w * y2;
-    double wz = w * z2;
+    final Float64List arg1Storage = arg1._qStorage;
+    final double x = arg1Storage[0];
+    final double y = arg1Storage[1];
+    final double z = arg1Storage[2];
+    final double w = arg1Storage[3];
+    final double x2 = x + x;
+    final double y2 = y + y;
+    final double z2 = z + z;
+    final double xx = x * x2;
+    final double xy = x * y2;
+    final double xz = x * z2;
+    final double yy = y * y2;
+    final double yz = y * z2;
+    final double zz = z * z2;
+    final double wx = w * x2;
+    final double wy = w * y2;
+    final double wz = w * z2;
 
-    final arg0Storage = arg0._v3storage;
+    final Float64List arg0Storage = arg0._v3storage;
     _m4storage[0] = 1.0 - (yy + zz);
     _m4storage[1] = xy + wz;
     _m4storage[2] = xz - wy;
@@ -460,7 +457,7 @@
 
   /// Sets the upper 2x2 of the matrix to be [arg].
   void setUpper2x2(Matrix2 arg) {
-    final argStorage = arg._m2storage;
+    final Float64List argStorage = arg._m2storage;
     _m4storage[0] = argStorage[0];
     _m4storage[1] = argStorage[1];
     _m4storage[4] = argStorage[2];
@@ -469,7 +466,7 @@
 
   /// Sets the diagonal of the matrix to be [arg].
   void setDiagonal(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _m4storage[0] = argStorage[0];
     _m4storage[5] = argStorage[1];
     _m4storage[10] = argStorage[2];
@@ -477,8 +474,8 @@
   }
 
   void setOuter(Vector4 u, Vector4 v) {
-    final uStorage = u._v4storage;
-    final vStorage = v._v4storage;
+    final Float64List uStorage = u._v4storage;
+    final Float64List vStorage = v._v4storage;
     _m4storage[0] = uStorage[0] * vStorage[0];
     _m4storage[1] = uStorage[0] * vStorage[1];
     _m4storage[2] = uStorage[0] * vStorage[2];
@@ -498,6 +495,7 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n'
       '[2] ${getRow(2)}\n[3] ${getRow(3)}\n';
 
@@ -513,26 +511,27 @@
   }
 
   /// Check if two matrices are the same.
-  bool operator ==(other) {
-    return (other is Matrix4) &&
-        (_m4storage[0] == other._m4storage[0]) &&
-        (_m4storage[1] == other._m4storage[1]) &&
-        (_m4storage[2] == other._m4storage[2]) &&
-        (_m4storage[3] == other._m4storage[3]) &&
-        (_m4storage[4] == other._m4storage[4]) &&
-        (_m4storage[5] == other._m4storage[5]) &&
-        (_m4storage[6] == other._m4storage[6]) &&
-        (_m4storage[7] == other._m4storage[7]) &&
-        (_m4storage[8] == other._m4storage[8]) &&
-        (_m4storage[9] == other._m4storage[9]) &&
-        (_m4storage[10] == other._m4storage[10]) &&
-        (_m4storage[11] == other._m4storage[11]) &&
-        (_m4storage[12] == other._m4storage[12]) &&
-        (_m4storage[13] == other._m4storage[13]) &&
-        (_m4storage[14] == other._m4storage[14]) &&
-        (_m4storage[15] == other._m4storage[15]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Matrix4) &&
+      (_m4storage[0] == other._m4storage[0]) &&
+      (_m4storage[1] == other._m4storage[1]) &&
+      (_m4storage[2] == other._m4storage[2]) &&
+      (_m4storage[3] == other._m4storage[3]) &&
+      (_m4storage[4] == other._m4storage[4]) &&
+      (_m4storage[5] == other._m4storage[5]) &&
+      (_m4storage[6] == other._m4storage[6]) &&
+      (_m4storage[7] == other._m4storage[7]) &&
+      (_m4storage[8] == other._m4storage[8]) &&
+      (_m4storage[9] == other._m4storage[9]) &&
+      (_m4storage[10] == other._m4storage[10]) &&
+      (_m4storage[11] == other._m4storage[11]) &&
+      (_m4storage[12] == other._m4storage[12]) &&
+      (_m4storage[13] == other._m4storage[13]) &&
+      (_m4storage[14] == other._m4storage[14]) &&
+      (_m4storage[15] == other._m4storage[15]);
 
+  @override
   int get hashCode => quiver.hashObjects(_m4storage);
 
   /// Returns row 0
@@ -561,7 +560,7 @@
 
   /// Assigns the [row] of the matrix [arg]
   void setRow(int row, Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _m4storage[index(row, 0)] = argStorage[0];
     _m4storage[index(row, 1)] = argStorage[1];
     _m4storage[index(row, 2)] = argStorage[2];
@@ -570,8 +569,8 @@
 
   /// Gets the [row] of the matrix
   Vector4 getRow(int row) {
-    Vector4 r = new Vector4.zero();
-    final rStorage = r._v4storage;
+    final Vector4 r = new Vector4.zero();
+    final Float64List rStorage = r._v4storage;
     rStorage[0] = _m4storage[index(row, 0)];
     rStorage[1] = _m4storage[index(row, 1)];
     rStorage[2] = _m4storage[index(row, 2)];
@@ -581,8 +580,8 @@
 
   /// Assigns the [column] of the matrix [arg]
   void setColumn(int column, Vector4 arg) {
-    int entry = column * 4;
-    final argStorage = arg._v4storage;
+    final int entry = column * 4;
+    final Float64List argStorage = arg._v4storage;
     _m4storage[entry + 3] = argStorage[3];
     _m4storage[entry + 2] = argStorage[2];
     _m4storage[entry + 1] = argStorage[1];
@@ -591,9 +590,9 @@
 
   /// Gets the [column] of the matrix
   Vector4 getColumn(int column) {
-    Vector4 r = new Vector4.zero();
-    final rStorage = r._v4storage;
-    int entry = column * 4;
+    final Vector4 r = new Vector4.zero();
+    final Float64List rStorage = r._v4storage;
+    final int entry = column * 4;
     rStorage[3] = _m4storage[entry + 3];
     rStorage[2] = _m4storage[entry + 2];
     rStorage[1] = _m4storage[entry + 1];
@@ -606,7 +605,7 @@
 
   /// Copy into [arg].
   Matrix4 copyInto(Matrix4 arg) {
-    final argStorage = arg._m4storage;
+    final Float64List argStorage = arg._m4storage;
     argStorage[0] = _m4storage[0];
     argStorage[1] = _m4storage[1];
     argStorage[2] = _m4storage[2];
@@ -640,7 +639,7 @@
     if (arg is Vector3) {
       return transformed3(arg);
     }
-    if (arg.dimension == 4) {
+    if (arg is Matrix4) {
       return multiplied(arg);
     }
     throw new ArgumentError(arg);
@@ -653,33 +652,37 @@
   Matrix4 operator -(Matrix4 arg) => clone()..sub(arg);
 
   /// Translate this matrix by a [Vector3], [Vector4], or x,y,z
-  void translate(x, [double y = 0.0, double z = 0.0]) {
+  void translate(dynamic x, [double y = 0.0, double z = 0.0]) {
     double tx;
     double ty;
     double tz;
-    double tw = x is Vector4 ? x.w : 1.0;
-    if (x is Vector3 || x is Vector4) {
+    final double tw = x is Vector4 ? x.w : 1.0;
+    if (x is Vector3) {
       tx = x.x;
       ty = x.y;
       tz = x.z;
-    } else {
+    } else if (x is Vector4) {
+      tx = x.x;
+      ty = x.y;
+      tz = x.z;
+    } else if (x is double) {
       tx = x;
       ty = y;
       tz = z;
     }
-    var t1 = _m4storage[0] * tx +
+    final double t1 = _m4storage[0] * tx +
         _m4storage[4] * ty +
         _m4storage[8] * tz +
         _m4storage[12] * tw;
-    var t2 = _m4storage[1] * tx +
+    final double t2 = _m4storage[1] * tx +
         _m4storage[5] * ty +
         _m4storage[9] * tz +
         _m4storage[13] * tw;
-    var t3 = _m4storage[2] * tx +
+    final double t3 = _m4storage[2] * tx +
         _m4storage[6] * ty +
         _m4storage[10] * tz +
         _m4storage[14] * tw;
-    var t4 = _m4storage[3] * tx +
+    final double t4 = _m4storage[3] * tx +
         _m4storage[7] * ty +
         _m4storage[11] * tz +
         _m4storage[15] * tw;
@@ -691,16 +694,20 @@
 
   /// Multiply [this] by a translation from the left.
   /// The translation can be specified with a  [Vector3], [Vector4], or x, y, z.
-  void leftTranslate(x, [double y = 0.0, double z = 0.0]) {
+  void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) {
     double tx;
     double ty;
     double tz;
-    double tw = x is Vector4 ? x.w : 1.0;
-    if (x is Vector3 || x is Vector4) {
+    final double tw = x is Vector4 ? x.w : 1.0;
+    if (x is Vector3) {
       tx = x.x;
       ty = x.y;
       tz = x.z;
-    } else {
+    } else if (x is Vector4) {
+      tx = x.x;
+      ty = x.y;
+      tz = x.z;
+    } else if (x is double) {
       tx = x;
       ty = y;
       tz = z;
@@ -733,35 +740,47 @@
 
   /// Rotate this [angle] radians around [axis]
   void rotate(Vector3 axis, double angle) {
-    var len = axis.length;
-    final axisStorage = axis._v3storage;
-    var x = axisStorage[0] / len;
-    var y = axisStorage[1] / len;
-    var z = axisStorage[2] / len;
-    var c = Math.cos(angle);
-    var s = Math.sin(angle);
-    var C = 1.0 - c;
-    var m11 = x * x * C + c;
-    var m12 = x * y * C - z * s;
-    var m13 = x * z * C + y * s;
-    var m21 = y * x * C + z * s;
-    var m22 = y * y * C + c;
-    var m23 = y * z * C - x * s;
-    var m31 = z * x * C - y * s;
-    var m32 = z * y * C + x * s;
-    var m33 = z * z * C + c;
-    var t1 = _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31;
-    var t2 = _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31;
-    var t3 = _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31;
-    var t4 = _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31;
-    var t5 = _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32;
-    var t6 = _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32;
-    var t7 = _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32;
-    var t8 = _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32;
-    var t9 = _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33;
-    var t10 = _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33;
-    var t11 = _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33;
-    var t12 = _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33;
+    final double len = axis.length;
+    final Float64List axisStorage = axis._v3storage;
+    final double x = axisStorage[0] / len;
+    final double y = axisStorage[1] / len;
+    final double z = axisStorage[2] / len;
+    final double c = math.cos(angle);
+    final double s = math.sin(angle);
+    final double C = 1.0 - c;
+    final double m11 = x * x * C + c;
+    final double m12 = x * y * C - z * s;
+    final double m13 = x * z * C + y * s;
+    final double m21 = y * x * C + z * s;
+    final double m22 = y * y * C + c;
+    final double m23 = y * z * C - x * s;
+    final double m31 = z * x * C - y * s;
+    final double m32 = z * y * C + x * s;
+    final double m33 = z * z * C + c;
+    final double t1 =
+        _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31;
+    final double t2 =
+        _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31;
+    final double t3 =
+        _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31;
+    final double t4 =
+        _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31;
+    final double t5 =
+        _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32;
+    final double t6 =
+        _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32;
+    final double t7 =
+        _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32;
+    final double t8 =
+        _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32;
+    final double t9 =
+        _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33;
+    final double t10 =
+        _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33;
+    final double t11 =
+        _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33;
+    final double t12 =
+        _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33;
     _m4storage[0] = t1;
     _m4storage[1] = t2;
     _m4storage[2] = t3;
@@ -778,16 +797,16 @@
 
   /// Rotate this [angle] radians around X
   void rotateX(double angle) {
-    double cosAngle = Math.cos(angle);
-    double sinAngle = Math.sin(angle);
-    var t1 = _m4storage[4] * cosAngle + _m4storage[8] * sinAngle;
-    var t2 = _m4storage[5] * cosAngle + _m4storage[9] * sinAngle;
-    var t3 = _m4storage[6] * cosAngle + _m4storage[10] * sinAngle;
-    var t4 = _m4storage[7] * cosAngle + _m4storage[11] * sinAngle;
-    var t5 = _m4storage[4] * -sinAngle + _m4storage[8] * cosAngle;
-    var t6 = _m4storage[5] * -sinAngle + _m4storage[9] * cosAngle;
-    var t7 = _m4storage[6] * -sinAngle + _m4storage[10] * cosAngle;
-    var t8 = _m4storage[7] * -sinAngle + _m4storage[11] * cosAngle;
+    final double cosAngle = math.cos(angle);
+    final double sinAngle = math.sin(angle);
+    final double t1 = _m4storage[4] * cosAngle + _m4storage[8] * sinAngle;
+    final double t2 = _m4storage[5] * cosAngle + _m4storage[9] * sinAngle;
+    final double t3 = _m4storage[6] * cosAngle + _m4storage[10] * sinAngle;
+    final double t4 = _m4storage[7] * cosAngle + _m4storage[11] * sinAngle;
+    final double t5 = _m4storage[4] * -sinAngle + _m4storage[8] * cosAngle;
+    final double t6 = _m4storage[5] * -sinAngle + _m4storage[9] * cosAngle;
+    final double t7 = _m4storage[6] * -sinAngle + _m4storage[10] * cosAngle;
+    final double t8 = _m4storage[7] * -sinAngle + _m4storage[11] * cosAngle;
     _m4storage[4] = t1;
     _m4storage[5] = t2;
     _m4storage[6] = t3;
@@ -800,16 +819,16 @@
 
   /// Rotate this matrix [angle] radians around Y
   void rotateY(double angle) {
-    double cosAngle = Math.cos(angle);
-    double sinAngle = Math.sin(angle);
-    var t1 = _m4storage[0] * cosAngle + _m4storage[8] * -sinAngle;
-    var t2 = _m4storage[1] * cosAngle + _m4storage[9] * -sinAngle;
-    var t3 = _m4storage[2] * cosAngle + _m4storage[10] * -sinAngle;
-    var t4 = _m4storage[3] * cosAngle + _m4storage[11] * -sinAngle;
-    var t5 = _m4storage[0] * sinAngle + _m4storage[8] * cosAngle;
-    var t6 = _m4storage[1] * sinAngle + _m4storage[9] * cosAngle;
-    var t7 = _m4storage[2] * sinAngle + _m4storage[10] * cosAngle;
-    var t8 = _m4storage[3] * sinAngle + _m4storage[11] * cosAngle;
+    final double cosAngle = math.cos(angle);
+    final double sinAngle = math.sin(angle);
+    final double t1 = _m4storage[0] * cosAngle + _m4storage[8] * -sinAngle;
+    final double t2 = _m4storage[1] * cosAngle + _m4storage[9] * -sinAngle;
+    final double t3 = _m4storage[2] * cosAngle + _m4storage[10] * -sinAngle;
+    final double t4 = _m4storage[3] * cosAngle + _m4storage[11] * -sinAngle;
+    final double t5 = _m4storage[0] * sinAngle + _m4storage[8] * cosAngle;
+    final double t6 = _m4storage[1] * sinAngle + _m4storage[9] * cosAngle;
+    final double t7 = _m4storage[2] * sinAngle + _m4storage[10] * cosAngle;
+    final double t8 = _m4storage[3] * sinAngle + _m4storage[11] * cosAngle;
     _m4storage[0] = t1;
     _m4storage[1] = t2;
     _m4storage[2] = t3;
@@ -822,16 +841,16 @@
 
   /// Rotate this matrix [angle] radians around Z
   void rotateZ(double angle) {
-    double cosAngle = Math.cos(angle);
-    double sinAngle = Math.sin(angle);
-    var t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle;
-    var t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle;
-    var t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle;
-    var t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle;
-    var t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle;
-    var t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle;
-    var t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle;
-    var t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle;
+    final double cosAngle = math.cos(angle);
+    final double sinAngle = math.sin(angle);
+    final double t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle;
+    final double t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle;
+    final double t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle;
+    final double t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle;
+    final double t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle;
+    final double t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle;
+    final double t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle;
+    final double t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle;
     _m4storage[0] = t1;
     _m4storage[1] = t2;
     _m4storage[2] = t3;
@@ -843,16 +862,20 @@
   }
 
   /// Scale this matrix by a [Vector3], [Vector4], or x,y,z
-  void scale(x, [double y, double z]) {
+  void scale(dynamic x, [double y, double z]) {
     double sx;
     double sy;
     double sz;
-    double sw = x is Vector4 ? x.w : 1.0;
-    if (x is Vector3 || x is Vector4) {
+    final double sw = x is Vector4 ? x.w : 1.0;
+    if (x is Vector3) {
       sx = x.x;
       sy = x.y;
       sz = x.z;
-    } else {
+    } else if (x is Vector4) {
+      sx = x.x;
+      sy = x.y;
+      sz = x.z;
+    } else if (x is double) {
       sx = x;
       sy = y == null ? x : y.toDouble();
       sz = z == null ? x : z.toDouble();
@@ -877,7 +900,7 @@
 
   /// Create a copy of [this] scaled by a [Vector3], [Vector4] or [x],[y], and
   /// [z].
-  Matrix4 scaled(x, [double y = null, double z = null]) =>
+  Matrix4 scaled(dynamic x, [double y = null, double z = null]) =>
       clone()..scale(x, y, z);
 
   /// Zeros [this].
@@ -947,8 +970,8 @@
 
   /// Returns the component wise absolute value of this.
   Matrix4 absolute() {
-    Matrix4 r = new Matrix4.zero();
-    final rStorage = r._m4storage;
+    final Matrix4 r = new Matrix4.zero();
+    final Float64List rStorage = r._m4storage;
     rStorage[0] = _m4storage[0].abs();
     rStorage[1] = _m4storage[1].abs();
     rStorage[2] = _m4storage[2].abs();
@@ -970,28 +993,28 @@
 
   /// Returns the determinant of this matrix.
   double determinant() {
-    double det2_01_01 =
+    final double det2_01_01 =
         _m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4];
-    double det2_01_02 =
+    final double det2_01_02 =
         _m4storage[0] * _m4storage[6] - _m4storage[2] * _m4storage[4];
-    double det2_01_03 =
+    final double det2_01_03 =
         _m4storage[0] * _m4storage[7] - _m4storage[3] * _m4storage[4];
-    double det2_01_12 =
+    final double det2_01_12 =
         _m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5];
-    double det2_01_13 =
+    final double det2_01_13 =
         _m4storage[1] * _m4storage[7] - _m4storage[3] * _m4storage[5];
-    double det2_01_23 =
+    final double det2_01_23 =
         _m4storage[2] * _m4storage[7] - _m4storage[3] * _m4storage[6];
-    double det3_201_012 = _m4storage[8] * det2_01_12 -
+    final double det3_201_012 = _m4storage[8] * det2_01_12 -
         _m4storage[9] * det2_01_02 +
         _m4storage[10] * det2_01_01;
-    double det3_201_013 = _m4storage[8] * det2_01_13 -
+    final double det3_201_013 = _m4storage[8] * det2_01_13 -
         _m4storage[9] * det2_01_03 +
         _m4storage[11] * det2_01_01;
-    double det3_201_023 = _m4storage[8] * det2_01_23 -
+    final double det3_201_023 = _m4storage[8] * det2_01_23 -
         _m4storage[10] * det2_01_03 +
         _m4storage[11] * det2_01_02;
-    double det3_201_123 = _m4storage[9] * det2_01_23 -
+    final double det3_201_123 = _m4storage[9] * det2_01_23 -
         _m4storage[10] * det2_01_13 +
         _m4storage[11] * det2_01_12;
     return -det3_201_123 * _m4storage[12] +
@@ -1002,7 +1025,7 @@
 
   /// Returns the dot product of row [i] and [v].
   double dotRow(int i, Vector4 v) {
-    final vStorage = v._v4storage;
+    final Float64List vStorage = v._v4storage;
     return _m4storage[i] * vStorage[0] +
         _m4storage[4 + i] * vStorage[1] +
         _m4storage[8 + i] * vStorage[2] +
@@ -1011,7 +1034,7 @@
 
   /// Returns the dot product of column [j] and [v].
   double dotColumn(int j, Vector4 v) {
-    final vStorage = v._v4storage;
+    final Float64List vStorage = v._v4storage;
     return _m4storage[j * 4] * vStorage[0] +
         _m4storage[j * 4 + 1] * vStorage[1] +
         _m4storage[j * 4 + 2] * vStorage[2] +
@@ -1069,34 +1092,34 @@
 
   /// Returns relative error between [this] and [correct]
   double relativeError(Matrix4 correct) {
-    Matrix4 diff = correct - this;
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = diff.infinityNorm();
+    final Matrix4 diff = correct - this;
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = diff.infinityNorm();
     return diff_norm / correct_norm;
   }
 
   /// Returns absolute error between [this] and [correct]
   double absoluteError(Matrix4 correct) {
-    double this_norm = infinityNorm();
-    double correct_norm = correct.infinityNorm();
-    double diff_norm = (this_norm - correct_norm).abs();
+    final double this_norm = infinityNorm();
+    final double correct_norm = correct.infinityNorm();
+    final double diff_norm = (this_norm - correct_norm).abs();
     return diff_norm;
   }
 
   /// Returns the translation vector from this homogeneous transformation matrix.
   Vector3 getTranslation() {
-    double z = _m4storage[14];
-    double y = _m4storage[13];
-    double x = _m4storage[12];
+    final double z = _m4storage[14];
+    final double y = _m4storage[13];
+    final double x = _m4storage[12];
     return new Vector3(x, y, z);
   }
 
   /// Sets the translation vector in this homogeneous transformation matrix.
   void setTranslation(Vector3 t) {
-    final tStorage = t._v3storage;
-    double z = tStorage[2];
-    double y = tStorage[1];
-    double x = tStorage[0];
+    final Float64List tStorage = t._v3storage;
+    final double z = tStorage[2];
+    final double y = tStorage[1];
+    final double x = tStorage[0];
     _m4storage[14] = z;
     _m4storage[13] = y;
     _m4storage[12] = x;
@@ -1111,7 +1134,7 @@
 
   /// Returns the rotation matrix from this homogeneous transformation matrix.
   Matrix3 getRotation() {
-    Matrix3 r = new Matrix3.zero();
+    final Matrix3 r = new Matrix3.zero();
     copyRotation(r);
     return r;
   }
@@ -1119,7 +1142,7 @@
   /// Copies the rotation matrix from this homogeneous transformation matrix
   /// into [rotation].
   void copyRotation(Matrix3 rotation) {
-    final rStorage = rotation._m3storage;
+    final Float64List rStorage = rotation._m3storage;
     rStorage[0] = _m4storage[0];
     rStorage[1] = _m4storage[1];
     rStorage[2] = _m4storage[2];
@@ -1133,7 +1156,7 @@
 
   /// Sets the rotation matrix in this homogeneous transformation matrix.
   void setRotation(Matrix3 r) {
-    final rStorage = r._m3storage;
+    final Float64List rStorage = r._m3storage;
     _m4storage[0] = rStorage[0];
     _m4storage[1] = rStorage[1];
     _m4storage[2] = rStorage[2];
@@ -1151,16 +1174,16 @@
 
   /// Returns the max scale value of the 3 axes.
   double getMaxScaleOnAxis() {
-    final scaleXSq = _m4storage[0] * _m4storage[0] +
+    final double scaleXSq = _m4storage[0] * _m4storage[0] +
         _m4storage[1] * _m4storage[1] +
         _m4storage[2] * _m4storage[2];
-    final scaleYSq = _m4storage[4] * _m4storage[4] +
+    final double scaleYSq = _m4storage[4] * _m4storage[4] +
         _m4storage[5] * _m4storage[5] +
         _m4storage[6] * _m4storage[6];
-    final scaleZSq = _m4storage[8] * _m4storage[8] +
+    final double scaleZSq = _m4storage[8] * _m4storage[8] +
         _m4storage[9] * _m4storage[9] +
         _m4storage[10] * _m4storage[10];
-    return Math.sqrt(Math.max(scaleXSq, Math.max(scaleYSq, scaleZSq)));
+    return math.sqrt(math.max(scaleXSq, math.max(scaleYSq, scaleZSq)));
   }
 
   /// Transposes just the upper 3x3 rotation matrix.
@@ -1191,42 +1214,42 @@
 
   /// Set this matrix to be the inverse of [arg]
   double copyInverse(Matrix4 arg) {
-    final argStorage = arg._m4storage;
-    double a00 = argStorage[0];
-    double a01 = argStorage[1];
-    double a02 = argStorage[2];
-    double a03 = argStorage[3];
-    double a10 = argStorage[4];
-    double a11 = argStorage[5];
-    double a12 = argStorage[6];
-    double a13 = argStorage[7];
-    double a20 = argStorage[8];
-    double a21 = argStorage[9];
-    double a22 = argStorage[10];
-    double a23 = argStorage[11];
-    double a30 = argStorage[12];
-    double a31 = argStorage[13];
-    double a32 = argStorage[14];
-    double a33 = argStorage[15];
-    var b00 = a00 * a11 - a01 * a10;
-    var b01 = a00 * a12 - a02 * a10;
-    var b02 = a00 * a13 - a03 * a10;
-    var b03 = a01 * a12 - a02 * a11;
-    var b04 = a01 * a13 - a03 * a11;
-    var b05 = a02 * a13 - a03 * a12;
-    var b06 = a20 * a31 - a21 * a30;
-    var b07 = a20 * a32 - a22 * a30;
-    var b08 = a20 * a33 - a23 * a30;
-    var b09 = a21 * a32 - a22 * a31;
-    var b10 = a21 * a33 - a23 * a31;
-    var b11 = a22 * a33 - a23 * a32;
-    var det =
+    final Float64List argStorage = arg._m4storage;
+    final double a00 = argStorage[0];
+    final double a01 = argStorage[1];
+    final double a02 = argStorage[2];
+    final double a03 = argStorage[3];
+    final double a10 = argStorage[4];
+    final double a11 = argStorage[5];
+    final double a12 = argStorage[6];
+    final double a13 = argStorage[7];
+    final double a20 = argStorage[8];
+    final double a21 = argStorage[9];
+    final double a22 = argStorage[10];
+    final double a23 = argStorage[11];
+    final double a30 = argStorage[12];
+    final double a31 = argStorage[13];
+    final double a32 = argStorage[14];
+    final double a33 = argStorage[15];
+    final double b00 = a00 * a11 - a01 * a10;
+    final double b01 = a00 * a12 - a02 * a10;
+    final double b02 = a00 * a13 - a03 * a10;
+    final double b03 = a01 * a12 - a02 * a11;
+    final double b04 = a01 * a13 - a03 * a11;
+    final double b05 = a02 * a13 - a03 * a12;
+    final double b06 = a20 * a31 - a21 * a30;
+    final double b07 = a20 * a32 - a22 * a30;
+    final double b08 = a20 * a33 - a23 * a30;
+    final double b09 = a21 * a32 - a22 * a31;
+    final double b10 = a21 * a33 - a23 * a31;
+    final double b11 = a22 * a33 - a23 * a32;
+    final double det =
         (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
     if (det == 0.0) {
       setFrom(arg);
       return 0.0;
     }
-    var invDet = 1.0 / det;
+    final double invDet = 1.0 / det;
     _m4storage[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
     _m4storage[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
     _m4storage[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
@@ -1247,11 +1270,11 @@
   }
 
   double invertRotation() {
-    double det = determinant();
+    final double det = determinant();
     if (det == 0.0) {
       return 0.0;
     }
-    double invDet = 1.0 / det;
+    final double invDet = 1.0 / det;
     double ix;
     double iy;
     double iz;
@@ -1293,8 +1316,8 @@
 
   /// Sets the upper 3x3 to a rotation of [radians] around X
   void setRotationX(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m4storage[0] = 1.0;
     _m4storage[1] = 0.0;
     _m4storage[2] = 0.0;
@@ -1311,8 +1334,8 @@
 
   /// Sets the upper 3x3 to a rotation of [radians] around Y
   void setRotationY(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m4storage[0] = c;
     _m4storage[1] = 0.0;
     _m4storage[2] = -s;
@@ -1329,8 +1352,8 @@
 
   /// Sets the upper 3x3 to a rotation of [radians] around Z
   void setRotationZ(double radians) {
-    double c = Math.cos(radians);
-    double s = Math.sin(radians);
+    final double c = math.cos(radians);
+    final double s = math.sin(radians);
     _m4storage[0] = c;
     _m4storage[1] = s;
     _m4storage[2] = 0.0;
@@ -1348,22 +1371,22 @@
   /// Converts into Adjugate matrix and scales by [scale]
   void scaleAdjoint(double scale) {
     // Adapted from code by Richard Carling.
-    double a1 = _m4storage[0];
-    double b1 = _m4storage[4];
-    double c1 = _m4storage[8];
-    double d1 = _m4storage[12];
-    double a2 = _m4storage[1];
-    double b2 = _m4storage[5];
-    double c2 = _m4storage[9];
-    double d2 = _m4storage[13];
-    double a3 = _m4storage[2];
-    double b3 = _m4storage[6];
-    double c3 = _m4storage[10];
-    double d3 = _m4storage[14];
-    double a4 = _m4storage[3];
-    double b4 = _m4storage[7];
-    double c4 = _m4storage[11];
-    double d4 = _m4storage[15];
+    final double a1 = _m4storage[0];
+    final double b1 = _m4storage[4];
+    final double c1 = _m4storage[8];
+    final double d1 = _m4storage[12];
+    final double a2 = _m4storage[1];
+    final double b2 = _m4storage[5];
+    final double c2 = _m4storage[9];
+    final double d2 = _m4storage[13];
+    final double a3 = _m4storage[2];
+    final double b3 = _m4storage[6];
+    final double c3 = _m4storage[10];
+    final double d3 = _m4storage[14];
+    final double a4 = _m4storage[3];
+    final double b4 = _m4storage[7];
+    final double c4 = _m4storage[11];
+    final double d4 = _m4storage[15];
     _m4storage[0] = (b2 * (c3 * d4 - c4 * d3) -
             c2 * (b3 * d4 - b4 * d3) +
             d2 * (b3 * c4 - b4 * c3)) *
@@ -1434,19 +1457,19 @@
   /// Returns [arg].
   /// Primarily used by AABB transformation code.
   Vector3 absoluteRotate(Vector3 arg) {
-    double m00 = _m4storage[0].abs();
-    double m01 = _m4storage[4].abs();
-    double m02 = _m4storage[8].abs();
-    double m10 = _m4storage[1].abs();
-    double m11 = _m4storage[5].abs();
-    double m12 = _m4storage[9].abs();
-    double m20 = _m4storage[2].abs();
-    double m21 = _m4storage[6].abs();
-    double m22 = _m4storage[10].abs();
-    final argStorage = arg._v3storage;
-    double x = argStorage[0];
-    double y = argStorage[1];
-    double z = argStorage[2];
+    final double m00 = _m4storage[0].abs();
+    final double m01 = _m4storage[4].abs();
+    final double m02 = _m4storage[8].abs();
+    final double m10 = _m4storage[1].abs();
+    final double m11 = _m4storage[5].abs();
+    final double m12 = _m4storage[9].abs();
+    final double m20 = _m4storage[2].abs();
+    final double m21 = _m4storage[6].abs();
+    final double m22 = _m4storage[10].abs();
+    final Float64List argStorage = arg._v3storage;
+    final double x = argStorage[0];
+    final double y = argStorage[1];
+    final double z = argStorage[2];
     argStorage[0] = x * m00 + y * m01 + z * m02 + 0.0 * 0.0;
     argStorage[1] = x * m10 + y * m11 + z * m12 + 0.0 * 0.0;
     argStorage[2] = x * m20 + y * m21 + z * m22 + 0.0 * 0.0;
@@ -1455,7 +1478,7 @@
 
   /// Adds [o] to [this].
   void add(Matrix4 o) {
-    final oStorage = o._m4storage;
+    final Float64List oStorage = o._m4storage;
     _m4storage[0] = _m4storage[0] + oStorage[0];
     _m4storage[1] = _m4storage[1] + oStorage[1];
     _m4storage[2] = _m4storage[2] + oStorage[2];
@@ -1476,7 +1499,7 @@
 
   /// Subtracts [o] from [this].
   void sub(Matrix4 o) {
-    final oStorage = o._m4storage;
+    final Float64List oStorage = o._m4storage;
     _m4storage[0] = _m4storage[0] - oStorage[0];
     _m4storage[1] = _m4storage[1] - oStorage[1];
     _m4storage[2] = _m4storage[2] - oStorage[2];
@@ -1517,39 +1540,39 @@
 
   /// Multiply [this] by [arg].
   void multiply(Matrix4 arg) {
-    final m00 = _m4storage[0];
-    final m01 = _m4storage[4];
-    final m02 = _m4storage[8];
-    final m03 = _m4storage[12];
-    final m10 = _m4storage[1];
-    final m11 = _m4storage[5];
-    final m12 = _m4storage[9];
-    final m13 = _m4storage[13];
-    final m20 = _m4storage[2];
-    final m21 = _m4storage[6];
-    final m22 = _m4storage[10];
-    final m23 = _m4storage[14];
-    final m30 = _m4storage[3];
-    final m31 = _m4storage[7];
-    final m32 = _m4storage[11];
-    final m33 = _m4storage[15];
-    final argStorage = arg._m4storage;
-    final n00 = argStorage[0];
-    final n01 = argStorage[4];
-    final n02 = argStorage[8];
-    final n03 = argStorage[12];
-    final n10 = argStorage[1];
-    final n11 = argStorage[5];
-    final n12 = argStorage[9];
-    final n13 = argStorage[13];
-    final n20 = argStorage[2];
-    final n21 = argStorage[6];
-    final n22 = argStorage[10];
-    final n23 = argStorage[14];
-    final n30 = argStorage[3];
-    final n31 = argStorage[7];
-    final n32 = argStorage[11];
-    final n33 = argStorage[15];
+    final double m00 = _m4storage[0];
+    final double m01 = _m4storage[4];
+    final double m02 = _m4storage[8];
+    final double m03 = _m4storage[12];
+    final double m10 = _m4storage[1];
+    final double m11 = _m4storage[5];
+    final double m12 = _m4storage[9];
+    final double m13 = _m4storage[13];
+    final double m20 = _m4storage[2];
+    final double m21 = _m4storage[6];
+    final double m22 = _m4storage[10];
+    final double m23 = _m4storage[14];
+    final double m30 = _m4storage[3];
+    final double m31 = _m4storage[7];
+    final double m32 = _m4storage[11];
+    final double m33 = _m4storage[15];
+    final Float64List argStorage = arg._m4storage;
+    final double n00 = argStorage[0];
+    final double n01 = argStorage[4];
+    final double n02 = argStorage[8];
+    final double n03 = argStorage[12];
+    final double n10 = argStorage[1];
+    final double n11 = argStorage[5];
+    final double n12 = argStorage[9];
+    final double n13 = argStorage[13];
+    final double n20 = argStorage[2];
+    final double n21 = argStorage[6];
+    final double n22 = argStorage[10];
+    final double n23 = argStorage[14];
+    final double n30 = argStorage[3];
+    final double n31 = argStorage[7];
+    final double n32 = argStorage[11];
+    final double n33 = argStorage[15];
     _m4storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30);
     _m4storage[4] = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31);
     _m4storage[8] = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32);
@@ -1573,23 +1596,23 @@
 
   /// Multiply a transposed [this] with [arg].
   void transposeMultiply(Matrix4 arg) {
-    double m00 = _m4storage[0];
-    double m01 = _m4storage[1];
-    double m02 = _m4storage[2];
-    double m03 = _m4storage[3];
-    double m10 = _m4storage[4];
-    double m11 = _m4storage[5];
-    double m12 = _m4storage[6];
-    double m13 = _m4storage[7];
-    double m20 = _m4storage[8];
-    double m21 = _m4storage[9];
-    double m22 = _m4storage[10];
-    double m23 = _m4storage[11];
-    double m30 = _m4storage[12];
-    double m31 = _m4storage[13];
-    double m32 = _m4storage[14];
-    double m33 = _m4storage[15];
-    final argStorage = arg._m4storage;
+    final double m00 = _m4storage[0];
+    final double m01 = _m4storage[1];
+    final double m02 = _m4storage[2];
+    final double m03 = _m4storage[3];
+    final double m10 = _m4storage[4];
+    final double m11 = _m4storage[5];
+    final double m12 = _m4storage[6];
+    final double m13 = _m4storage[7];
+    final double m20 = _m4storage[8];
+    final double m21 = _m4storage[9];
+    final double m22 = _m4storage[10];
+    final double m23 = _m4storage[11];
+    final double m30 = _m4storage[12];
+    final double m31 = _m4storage[13];
+    final double m32 = _m4storage[14];
+    final double m33 = _m4storage[15];
+    final Float64List argStorage = arg._m4storage;
     _m4storage[0] = (m00 * argStorage[0]) +
         (m01 * argStorage[1]) +
         (m02 * argStorage[2]) +
@@ -1658,23 +1681,23 @@
 
   /// Multiply [this] with a transposed [arg].
   void multiplyTranspose(Matrix4 arg) {
-    double m00 = _m4storage[0];
-    double m01 = _m4storage[4];
-    double m02 = _m4storage[8];
-    double m03 = _m4storage[12];
-    double m10 = _m4storage[1];
-    double m11 = _m4storage[5];
-    double m12 = _m4storage[9];
-    double m13 = _m4storage[13];
-    double m20 = _m4storage[2];
-    double m21 = _m4storage[6];
-    double m22 = _m4storage[10];
-    double m23 = _m4storage[14];
-    double m30 = _m4storage[3];
-    double m31 = _m4storage[7];
-    double m32 = _m4storage[11];
-    double m33 = _m4storage[15];
-    final argStorage = arg._m4storage;
+    final double m00 = _m4storage[0];
+    final double m01 = _m4storage[4];
+    final double m02 = _m4storage[8];
+    final double m03 = _m4storage[12];
+    final double m10 = _m4storage[1];
+    final double m11 = _m4storage[5];
+    final double m12 = _m4storage[9];
+    final double m13 = _m4storage[13];
+    final double m20 = _m4storage[2];
+    final double m21 = _m4storage[6];
+    final double m22 = _m4storage[10];
+    final double m23 = _m4storage[14];
+    final double m30 = _m4storage[3];
+    final double m31 = _m4storage[7];
+    final double m32 = _m4storage[11];
+    final double m33 = _m4storage[15];
+    final Float64List argStorage = arg._m4storage;
     _m4storage[0] = (m00 * argStorage[0]) +
         (m01 * argStorage[4]) +
         (m02 * argStorage[8]) +
@@ -1743,23 +1766,27 @@
 
   /// Decomposes [this] into [translation], [rotation] and [scale] components.
   void decompose(Vector3 translation, Quaternion rotation, Vector3 scale) {
-    final v = new Vector3.zero();
-    var sx = (v..setValues(_m4storage[0], _m4storage[1], _m4storage[2])).length;
-    var sy = (v..setValues(_m4storage[4], _m4storage[5], _m4storage[6])).length;
-    var sz =
+    final Vector3 v = new Vector3.zero();
+    double sx =
+        (v..setValues(_m4storage[0], _m4storage[1], _m4storage[2])).length;
+    final double sy =
+        (v..setValues(_m4storage[4], _m4storage[5], _m4storage[6])).length;
+    final double sz =
         (v..setValues(_m4storage[8], _m4storage[9], _m4storage[10])).length;
 
-    if (determinant() < 0) sx = -sx;
+    if (determinant() < 0) {
+      sx = -sx;
+    }
 
     translation._v3storage[0] = _m4storage[12];
     translation._v3storage[1] = _m4storage[13];
     translation._v3storage[2] = _m4storage[14];
 
-    final invSX = 1.0 / sx;
-    final invSY = 1.0 / sy;
-    final invSZ = 1.0 / sz;
+    final double invSX = 1.0 / sx;
+    final double invSY = 1.0 / sy;
+    final double invSZ = 1.0 / sz;
 
-    final m = new Matrix4.copy(this);
+    final Matrix4 m = new Matrix4.copy(this);
     m._m4storage[0] *= invSX;
     m._m4storage[1] *= invSX;
     m._m4storage[2] *= invSX;
@@ -1779,14 +1806,14 @@
 
   /// Rotate [arg] of type [Vector3] using the rotation defined by [this].
   Vector3 rotate3(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float64List argStorage = arg._v3storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]);
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]);
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]);
     argStorage[0] = x_;
@@ -1809,16 +1836,16 @@
   /// Transform [arg] of type [Vector3] using the transformation defined by
   /// [this].
   Vector3 transform3(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float64List argStorage = arg._v3storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]) +
         _m4storage[12];
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]) +
         _m4storage[13];
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]) +
         _m4storage[14];
@@ -1843,20 +1870,20 @@
   /// Transform [arg] of type [Vector4] using the transformation defined by
   /// [this].
   Vector4 transform(Vector4 arg) {
-    final argStorage = arg._v4storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float64List argStorage = arg._v4storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]) +
         (_m4storage[12] * argStorage[3]);
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]) +
         (_m4storage[13] * argStorage[3]);
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]) +
         (_m4storage[14] * argStorage[3]);
-    final w_ = (_m4storage[3] * argStorage[0]) +
+    final double w_ = (_m4storage[3] * argStorage[0]) +
         (_m4storage[7] * argStorage[1]) +
         (_m4storage[11] * argStorage[2]) +
         (_m4storage[15] * argStorage[3]);
@@ -1870,20 +1897,20 @@
   /// Transform [arg] of type [Vector3] using the perspective transformation
   /// defined by [this].
   Vector3 perspectiveTransform(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final x_ = (_m4storage[0] * argStorage[0]) +
+    final Float64List argStorage = arg._v3storage;
+    final double x_ = (_m4storage[0] * argStorage[0]) +
         (_m4storage[4] * argStorage[1]) +
         (_m4storage[8] * argStorage[2]) +
         _m4storage[12];
-    final y_ = (_m4storage[1] * argStorage[0]) +
+    final double y_ = (_m4storage[1] * argStorage[0]) +
         (_m4storage[5] * argStorage[1]) +
         (_m4storage[9] * argStorage[2]) +
         _m4storage[13];
-    final z_ = (_m4storage[2] * argStorage[0]) +
+    final double z_ = (_m4storage[2] * argStorage[0]) +
         (_m4storage[6] * argStorage[1]) +
         (_m4storage[10] * argStorage[2]) +
         _m4storage[14];
-    final w_ = 1.0 /
+    final double w_ = 1.0 /
         ((_m4storage[3] * argStorage[0]) +
             (_m4storage[7] * argStorage[1]) +
             (_m4storage[11] * argStorage[2]) +
@@ -1908,7 +1935,7 @@
 
   /// Copies [this] into [array] starting at [offset].
   void copyIntoArray(List<num> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     array[i + 15] = _m4storage[15];
     array[i + 14] = _m4storage[14];
     array[i + 13] = _m4storage[13];
@@ -1929,7 +1956,7 @@
 
   /// Copies elements from [array] into [this] starting at [offset].
   void copyFromArray(List<double> array, [int offset = 0]) {
-    int i = offset;
+    final int i = offset;
     _m4storage[15] = array[i + 15];
     _m4storage[14] = array[i + 14];
     _m4storage[13] = array[i + 13];
@@ -1950,8 +1977,8 @@
 
   /// Multiply [this] to each set of xyz values in [array] starting at [offset].
   List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
-    for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
-      final v = new Vector3.array(array, j)..applyMatrix4(this);
+    for (int i = 0, j = offset; i < array.length; i += 3, j += 3) {
+      final Vector3 v = new Vector3.array(array, j)..applyMatrix4(this);
       array[j] = v.storage[0];
       array[j + 1] = v.storage[1];
       array[j + 2] = v.storage[2];
@@ -1961,63 +1988,69 @@
   }
 
   Vector3 get right {
-    double x = _m4storage[0];
-    double y = _m4storage[1];
-    double z = _m4storage[2];
+    final double x = _m4storage[0];
+    final double y = _m4storage[1];
+    final double z = _m4storage[2];
     return new Vector3(x, y, z);
   }
 
   Vector3 get up {
-    double x = _m4storage[4];
-    double y = _m4storage[5];
-    double z = _m4storage[6];
+    final double x = _m4storage[4];
+    final double y = _m4storage[5];
+    final double z = _m4storage[6];
     return new Vector3(x, y, z);
   }
 
   Vector3 get forward {
-    double x = _m4storage[8];
-    double y = _m4storage[9];
-    double z = _m4storage[10];
+    final double x = _m4storage[8];
+    final double y = _m4storage[9];
+    final double z = _m4storage[10];
     return new Vector3(x, y, z);
   }
 
   /// Is [this] the identity matrix?
-  bool isIdentity() {
-    return _m4storage[0] == 1.0 // col 1
-        && _m4storage[1] == 0.0
-        && _m4storage[2] == 0.0
-        && _m4storage[3] == 0.0
-        && _m4storage[4] == 0.0 // col 2
-        && _m4storage[5] == 1.0
-        && _m4storage[6] == 0.0
-        && _m4storage[7] == 0.0
-        && _m4storage[8] == 0.0 // col 3
-        && _m4storage[9] == 0.0
-        && _m4storage[10] == 1.0
-        && _m4storage[11] == 0.0
-        && _m4storage[12] == 0.0 // col 4
-        && _m4storage[13] == 0.0
-        && _m4storage[14] == 0.0
-        && _m4storage[15] == 1.0;
-  }
+  bool isIdentity() =>
+      _m4storage[0] == 1.0 // col 1
+      &&
+      _m4storage[1] == 0.0 &&
+      _m4storage[2] == 0.0 &&
+      _m4storage[3] == 0.0 &&
+      _m4storage[4] == 0.0 // col 2
+      &&
+      _m4storage[5] == 1.0 &&
+      _m4storage[6] == 0.0 &&
+      _m4storage[7] == 0.0 &&
+      _m4storage[8] == 0.0 // col 3
+      &&
+      _m4storage[9] == 0.0 &&
+      _m4storage[10] == 1.0 &&
+      _m4storage[11] == 0.0 &&
+      _m4storage[12] == 0.0 // col 4
+      &&
+      _m4storage[13] == 0.0 &&
+      _m4storage[14] == 0.0 &&
+      _m4storage[15] == 1.0;
 
   /// Is [this] the zero matrix?
-  bool isZero() {
-    return _m4storage[0] == 0.0 // col 1
-        && _m4storage[1] == 0.0
-        && _m4storage[2] == 0.0
-        && _m4storage[3] == 0.0
-        && _m4storage[4] == 0.0 // col 2
-        && _m4storage[5] == 0.0
-        && _m4storage[6] == 0.0
-        && _m4storage[7] == 0.0
-        && _m4storage[8] == 0.0 // col 3
-        && _m4storage[9] == 0.0
-        && _m4storage[10] == 0.0
-        && _m4storage[11] == 0.0
-        && _m4storage[12] == 0.0 // col 4
-        && _m4storage[13] == 0.0
-        && _m4storage[14] == 0.0
-        && _m4storage[15] == 0.0;
-  }
+  bool isZero() =>
+      _m4storage[0] == 0.0 // col 1
+      &&
+      _m4storage[1] == 0.0 &&
+      _m4storage[2] == 0.0 &&
+      _m4storage[3] == 0.0 &&
+      _m4storage[4] == 0.0 // col 2
+      &&
+      _m4storage[5] == 0.0 &&
+      _m4storage[6] == 0.0 &&
+      _m4storage[7] == 0.0 &&
+      _m4storage[8] == 0.0 // col 3
+      &&
+      _m4storage[9] == 0.0 &&
+      _m4storage[10] == 0.0 &&
+      _m4storage[11] == 0.0 &&
+      _m4storage[12] == 0.0 // col 4
+      &&
+      _m4storage[13] == 0.0 &&
+      _m4storage[14] == 0.0 &&
+      _m4storage[15] == 0.0;
 }
diff --git a/pub/vector_math/lib/src/vector_math_64/obb3.dart b/pub/vector_math/lib/src/vector_math_64/obb3.dart
index 6966714..8114cb0 100644
--- a/pub/vector_math/lib/src/vector_math_64/obb3.dart
+++ b/pub/vector_math/lib/src/vector_math_64/obb3.dart
@@ -84,23 +84,29 @@
 
   /// Rotate [this] by the rotation matrix [t].
   void rotate(Matrix3 t) {
-    t.transform(_axis0..scale(_halfExtents.x));
-    t.transform(_axis1..scale(_halfExtents.y));
-    t.transform(_axis2..scale(_halfExtents.z));
-    _halfExtents.x = _axis0.normalize();
-    _halfExtents.y = _axis1.normalize();
-    _halfExtents.z = _axis2.normalize();
+    t
+      ..transform(_axis0..scale(_halfExtents.x))
+      ..transform(_axis1..scale(_halfExtents.y))
+      ..transform(_axis2..scale(_halfExtents.z));
+
+    _halfExtents
+      ..x = _axis0.normalize()
+      ..y = _axis1.normalize()
+      ..z = _axis2.normalize();
   }
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    t.transform3(_center);
-    t.rotate3(_axis0..scale(_halfExtents.x));
-    t.rotate3(_axis1..scale(_halfExtents.y));
-    t.rotate3(_axis2..scale(_halfExtents.z));
-    _halfExtents.x = _axis0.normalize();
-    _halfExtents.y = _axis1.normalize();
-    _halfExtents.z = _axis2.normalize();
+    t
+      ..transform3(_center)
+      ..rotate3(_axis0..scale(_halfExtents.x))
+      ..rotate3(_axis1..scale(_halfExtents.y))
+      ..rotate3(_axis2..scale(_halfExtents.z));
+
+    _halfExtents
+      ..x = _axis0.normalize()
+      ..y = _axis1.normalize()
+      ..z = _axis2.normalize();
   }
 
   /// Store the corner with [cornerIndex] in [corner].
@@ -163,40 +169,41 @@
 
   /// Find the closest point [q] on the OBB to the point [p] and store it in [q].
   void closestPointTo(Vector3 p, Vector3 q) {
-    final d = p - _center;
+    final Vector3 d = p - _center;
 
     q.setFrom(_center);
 
-    var dist = d.dot(_axis0);
-    dist = dist.clamp(-_halfExtents.x, _halfExtents.x);
+    double dist = d.dot(_axis0);
+    dist = dist.clamp(-_halfExtents.x, _halfExtents.x).toDouble();
     q.addScaled(_axis0, dist);
 
     dist = d.dot(_axis1);
-    dist = dist.clamp(-_halfExtents.y, _halfExtents.y);
+    dist = dist.clamp(-_halfExtents.y, _halfExtents.y).toDouble();
     q.addScaled(_axis1, dist);
 
     dist = d.dot(_axis2);
-    dist = dist.clamp(-_halfExtents.z, _halfExtents.z);
+    dist = dist.clamp(-_halfExtents.z, _halfExtents.z).toDouble();
     q.addScaled(_axis2, dist);
   }
 
   // Avoid allocating these instance on every call to intersectsWithObb3
-  static final _r = new Matrix3.zero();
-  static final _absR = new Matrix3.zero();
-  static final _t = new Vector3.zero();
+  static final Matrix3 _r = new Matrix3.zero();
+  static final Matrix3 _absR = new Matrix3.zero();
+  static final Vector3 _t = new Vector3.zero();
 
   /// Check for intersection between [this] and [other].
   bool intersectsWithObb3(Obb3 other, [double epsilon = 1e-3]) {
     // Compute rotation matrix expressing other in this's coordinate frame
-    _r.setEntry(0, 0, _axis0.dot(other._axis0));
-    _r.setEntry(1, 0, _axis1.dot(other._axis0));
-    _r.setEntry(2, 0, _axis2.dot(other._axis0));
-    _r.setEntry(0, 1, _axis0.dot(other._axis1));
-    _r.setEntry(1, 1, _axis1.dot(other._axis1));
-    _r.setEntry(2, 1, _axis2.dot(other._axis1));
-    _r.setEntry(0, 2, _axis0.dot(other._axis2));
-    _r.setEntry(1, 2, _axis1.dot(other._axis2));
-    _r.setEntry(2, 2, _axis2.dot(other._axis2));
+    _r
+      ..setEntry(0, 0, _axis0.dot(other._axis0))
+      ..setEntry(1, 0, _axis1.dot(other._axis0))
+      ..setEntry(2, 0, _axis2.dot(other._axis0))
+      ..setEntry(0, 1, _axis0.dot(other._axis1))
+      ..setEntry(1, 1, _axis1.dot(other._axis1))
+      ..setEntry(2, 1, _axis2.dot(other._axis1))
+      ..setEntry(0, 2, _axis0.dot(other._axis2))
+      ..setEntry(1, 2, _axis1.dot(other._axis2))
+      ..setEntry(2, 2, _axis2.dot(other._axis2));
 
     // Compute translation vector t
     _t
@@ -209,8 +216,8 @@
     // Compute common subexpressions. Add in an epsilon term to
     // counteract arithmetic errors when two edges are parallel and
     // their cross product is (near) null.
-    for (var i = 0; i < 3; i++) {
-      for (var j = 0; j < 3; j++) {
+    for (int i = 0; i < 3; i++) {
+      for (int j = 0; j < 3; j++) {
         _absR.setEntry(i, j, _r.entry(i, j).abs() + epsilon);
       }
     }
@@ -219,7 +226,7 @@
     double rb;
 
     // Test axes L = A0, L = A1, L = A2
-    for (var i = 0; i < 3; i++) {
+    for (int i = 0; i < 3; i++) {
       ra = _halfExtents[i];
       rb = other._halfExtents[0] * _absR.entry(i, 0) +
           other._halfExtents[1] * _absR.entry(i, 1) +
@@ -231,7 +238,7 @@
     }
 
     // Test axes L = B0, L = B1, L = B2
-    for (var i = 0; i < 3; i++) {
+    for (int i = 0; i < 3; i++) {
       ra = _halfExtents[0] * _absR.entry(0, i) +
           _halfExtents[1] * _absR.entry(1, i) +
           _halfExtents[2] * _absR.entry(2, i);
@@ -332,23 +339,26 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _triangle = new Triangle();
-  static final _aabb3 = new Aabb3();
-  static final _zeroVector = new Vector3.zero();
+  static final Triangle _triangle = new Triangle();
+  static final Aabb3 _aabb3 = new Aabb3();
+  static final Vector3 _zeroVector = new Vector3.zero();
 
   /// Return if [this] intersects with [other]
   bool intersectsWithTriangle(Triangle other, {IntersectionResult result}) {
     _triangle.copyFrom(other);
 
-    _triangle.point0.sub(_center);
-    _triangle.point0.setValues(_triangle.point0.dot(axis0),
-        _triangle.point0.dot(axis1), _triangle.point0.dot(axis2));
-    _triangle.point1.sub(_center);
-    _triangle.point1.setValues(_triangle.point1.dot(axis0),
-        _triangle.point1.dot(axis1), _triangle.point1.dot(axis2));
-    _triangle.point2.sub(_center);
-    _triangle.point2.setValues(_triangle.point2.dot(axis0),
-        _triangle.point2.dot(axis1), _triangle.point2.dot(axis2));
+    _triangle.point0
+      ..sub(_center)
+      ..setValues(_triangle.point0.dot(axis0), _triangle.point0.dot(axis1),
+          _triangle.point0.dot(axis2));
+    _triangle.point1
+      ..sub(_center)
+      ..setValues(_triangle.point1.dot(axis0), _triangle.point1.dot(axis1),
+          _triangle.point1.dot(axis2));
+    _triangle.point2
+      ..sub(_center)
+      ..setValues(_triangle.point2.dot(axis0), _triangle.point2.dot(axis1),
+          _triangle.point2.dot(axis2));
 
     _aabb3.setCenterAndHalfExtents(_zeroVector, _halfExtents);
 
@@ -356,15 +366,14 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithVector3
-  static final _vector = new Vector3.zero();
+  static final Vector3 _vector = new Vector3.zero();
 
   /// Return if [this] intersects with [other]
   bool intersectsWithVector3(Vector3 other) {
-    _vector.setFrom(other);
-
-    _vector.sub(_center);
-    _vector.setValues(
-        _vector.dot(axis0), _vector.dot(axis1), _vector.dot(axis2));
+    _vector
+      ..setFrom(other)
+      ..sub(_center)
+      ..setValues(_vector.dot(axis0), _vector.dot(axis1), _vector.dot(axis2));
 
     _aabb3.setCenterAndHalfExtents(_zeroVector, _halfExtents);
 
@@ -372,8 +381,8 @@
   }
 
   // Avoid allocating these instance on every call to intersectsWithTriangle
-  static final _quadTriangle0 = new Triangle();
-  static final _quadTriangle1 = new Triangle();
+  static final Triangle _quadTriangle0 = new Triangle();
+  static final Triangle _quadTriangle1 = new Triangle();
 
   /// Return if [this] intersects with [other]
   bool intersectsWithQuad(Quad other, {IntersectionResult result}) {
diff --git a/pub/vector_math/lib/src/vector_math_64/opengl.dart b/pub/vector_math/lib/src/vector_math_64/opengl.dart
index b53dfaa..994cc31 100644
--- a/pub/vector_math/lib/src/vector_math_64/opengl.dart
+++ b/pub/vector_math/lib/src/vector_math_64/opengl.dart
@@ -56,10 +56,10 @@
 /// [tx],[ty],[tz] specifies the position of the object.
 void setModelMatrix(Matrix4 modelMatrix, Vector3 forwardDirection,
     Vector3 upDirection, double tx, double ty, double tz) {
-  Vector3 right = forwardDirection.cross(upDirection)..normalize();
-  Vector3 c1 = right;
-  Vector3 c2 = upDirection;
-  Vector3 c3 = -forwardDirection;
+  final Vector3 right = forwardDirection.cross(upDirection)..normalize();
+  final Vector3 c1 = right;
+  final Vector3 c2 = upDirection;
+  final Vector3 c3 = -forwardDirection;
   modelMatrix.setValues(c1[0], c1[1], c1[2], 0.0, c2[0], c2[1], c2[2], 0.0,
       c3[0], c3[1], c3[2], 0.0, tx, ty, tz, 1.0);
 }
@@ -74,16 +74,13 @@
 /// [upDirection] specifies the direction of the up vector (usually, +Y).
 void setViewMatrix(Matrix4 viewMatrix, Vector3 cameraPosition,
     Vector3 cameraFocusPosition, Vector3 upDirection) {
-  Vector3 z = cameraPosition - cameraFocusPosition;
-  z.normalize();
-  Vector3 x = upDirection.cross(z);
-  x.normalize();
-  Vector3 y = z.cross(x);
-  y.normalize();
+  final Vector3 z = (cameraPosition - cameraFocusPosition)..normalize();
+  final Vector3 x = upDirection.cross(z)..normalize();
+  final Vector3 y = z.cross(x)..normalize();
 
-  double rotatedEyeX = -x.dot(cameraPosition);
-  double rotatedEyeY = -y.dot(cameraPosition);
-  double rotatedEyeZ = -z.dot(cameraPosition);
+  final double rotatedEyeX = -x.dot(cameraPosition);
+  final double rotatedEyeY = -y.dot(cameraPosition);
+  final double rotatedEyeZ = -z.dot(cameraPosition);
 
   viewMatrix.setValues(x[0], y[0], z[0], 0.0, x[1], y[1], z[1], 0.0, x[2], y[2],
       z[2], 0.0, rotatedEyeX, rotatedEyeY, rotatedEyeZ, 1.0);
@@ -96,7 +93,7 @@
 /// [upDirection] specifies the direction of the up vector (usually, +Y).
 Matrix4 makeViewMatrix(
     Vector3 cameraPosition, Vector3 cameraFocusPosition, Vector3 upDirection) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setViewMatrix(r, cameraPosition, cameraFocusPosition, upDirection);
   return r;
 }
@@ -113,16 +110,17 @@
 /// (always positive).
 void setPerspectiveMatrix(Matrix4 perspectiveMatrix, double fovYRadians,
     double aspectRatio, double zNear, double zFar) {
-  final double height = Math.tan(fovYRadians * 0.5);
+  final double height = math.tan(fovYRadians * 0.5);
   final double width = height * aspectRatio;
   final double near_minus_far = zNear - zFar;
 
-  final Matrix4 view = perspectiveMatrix..setZero();
-  view.setEntry(0, 0, 1.0 / width);
-  view.setEntry(1, 1, 1.0 / height);
-  view.setEntry(2, 2, (zFar + zNear) / near_minus_far);
-  view.setEntry(3, 2, -1.0);
-  view.setEntry(2, 3, (2.0 * zNear * zFar) / near_minus_far);
+  perspectiveMatrix
+    ..setZero()
+    ..setEntry(0, 0, 1.0 / width)
+    ..setEntry(1, 1, 1.0 / height)
+    ..setEntry(2, 2, (zFar + zNear) / near_minus_far)
+    ..setEntry(3, 2, -1.0)
+    ..setEntry(2, 3, (2.0 * zNear * zFar) / near_minus_far);
 }
 
 /// Constructs a new OpenGL perspective projection matrix.
@@ -137,7 +135,7 @@
 /// (always positive).
 Matrix4 makePerspectiveMatrix(
     double fovYRadians, double aspectRatio, double zNear, double zFar) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setPerspectiveMatrix(r, fovYRadians, aspectRatio, zNear, zFar);
   return r;
 }
@@ -151,15 +149,16 @@
 /// (always positive).
 void setInfiniteMatrix(Matrix4 infiniteMatrix, double fovYRadians,
     double aspectRatio, double zNear) {
-  final double height = Math.tan(fovYRadians * 0.5);
+  final double height = math.tan(fovYRadians * 0.5);
   final double width = height * aspectRatio;
 
-  final Matrix4 view = infiniteMatrix..setZero();
-  view.setEntry(0, 0, 1.0 / width);
-  view.setEntry(1, 1, 1.0 / height);
-  view.setEntry(2, 2, -1.0);
-  view.setEntry(3, 2, -1.0);
-  view.setEntry(2, 3, -2.0 * zNear);
+  infiniteMatrix
+    ..setZero()
+    ..setEntry(0, 0, 1.0 / width)
+    ..setEntry(1, 1, 1.0 / height)
+    ..setEntry(2, 2, -1.0)
+    ..setEntry(3, 2, -1.0)
+    ..setEntry(2, 3, -2.0 * zNear);
 }
 
 /// Constructs a new OpenGL infinite projection matrix.
@@ -172,7 +171,7 @@
 /// (always positive).
 Matrix4 makeInfiniteMatrix(
     double fovYRadians, double aspectRatio, double zNear) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setInfiniteMatrix(r, fovYRadians, aspectRatio, zNear);
   return r;
 }
@@ -187,18 +186,19 @@
 /// planes.
 void setFrustumMatrix(Matrix4 perspectiveMatrix, double left, double right,
     double bottom, double top, double near, double far) {
-  double two_near = 2.0 * near;
-  double right_minus_left = right - left;
-  double top_minus_bottom = top - bottom;
-  double far_minus_near = far - near;
-  Matrix4 view = perspectiveMatrix..setZero();
-  view.setEntry(0, 0, two_near / right_minus_left);
-  view.setEntry(1, 1, two_near / top_minus_bottom);
-  view.setEntry(0, 2, (right + left) / right_minus_left);
-  view.setEntry(1, 2, (top + bottom) / top_minus_bottom);
-  view.setEntry(2, 2, -(far + near) / far_minus_near);
-  view.setEntry(3, 2, -1.0);
-  view.setEntry(2, 3, -(two_near * far) / far_minus_near);
+  final double two_near = 2.0 * near;
+  final double right_minus_left = right - left;
+  final double top_minus_bottom = top - bottom;
+  final double far_minus_near = far - near;
+  perspectiveMatrix
+    ..setZero()
+    ..setEntry(0, 0, two_near / right_minus_left)
+    ..setEntry(1, 1, two_near / top_minus_bottom)
+    ..setEntry(0, 2, (right + left) / right_minus_left)
+    ..setEntry(1, 2, (top + bottom) / top_minus_bottom)
+    ..setEntry(2, 2, -(far + near) / far_minus_near)
+    ..setEntry(3, 2, -1.0)
+    ..setEntry(2, 3, -(two_near * far) / far_minus_near);
 }
 
 /// Constructs a new OpenGL perspective projection matrix.
@@ -211,7 +211,7 @@
 /// planes.
 Matrix4 makeFrustumMatrix(double left, double right, double bottom, double top,
     double near, double far) {
-  Matrix4 view = new Matrix4.zero();
+  final Matrix4 view = new Matrix4.zero();
   setFrustumMatrix(view, left, right, bottom, top, near, far);
   return view;
 }
@@ -226,20 +226,21 @@
 /// planes.
 void setOrthographicMatrix(Matrix4 orthographicMatrix, double left,
     double right, double bottom, double top, double near, double far) {
-  double rml = right - left;
-  double rpl = right + left;
-  double tmb = top - bottom;
-  double tpb = top + bottom;
-  double fmn = far - near;
-  double fpn = far + near;
-  Matrix4 r = orthographicMatrix..setZero();
-  r.setEntry(0, 0, 2.0 / rml);
-  r.setEntry(1, 1, 2.0 / tmb);
-  r.setEntry(2, 2, -2.0 / fmn);
-  r.setEntry(0, 3, -rpl / rml);
-  r.setEntry(1, 3, -tpb / tmb);
-  r.setEntry(2, 3, -fpn / fmn);
-  r.setEntry(3, 3, 1.0);
+  final double rml = right - left;
+  final double rpl = right + left;
+  final double tmb = top - bottom;
+  final double tpb = top + bottom;
+  final double fmn = far - near;
+  final double fpn = far + near;
+  orthographicMatrix
+    ..setZero()
+    ..setEntry(0, 0, 2.0 / rml)
+    ..setEntry(1, 1, 2.0 / tmb)
+    ..setEntry(2, 2, -2.0 / fmn)
+    ..setEntry(0, 3, -rpl / rml)
+    ..setEntry(1, 3, -tpb / tmb)
+    ..setEntry(2, 3, -fpn / fmn)
+    ..setEntry(3, 3, 1.0);
 }
 
 /// Constructs a new OpenGL orthographic projection matrix.
@@ -252,7 +253,7 @@
 /// planes.
 Matrix4 makeOrthographicMatrix(double left, double right, double bottom,
     double top, double near, double far) {
-  Matrix4 r = new Matrix4.zero();
+  final Matrix4 r = new Matrix4.zero();
   setOrthographicMatrix(r, left, right, bottom, top, near, far);
   return r;
 }
@@ -260,14 +261,15 @@
 /// Returns a transformation matrix that transforms points onto
 /// the plane specified with [planeNormal] and [planePoint].
 Matrix4 makePlaneProjection(Vector3 planeNormal, Vector3 planePoint) {
-  Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
+  final Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
       planeNormal.storage[2], 0.0);
-  Matrix4 outer = new Matrix4.outer(v, v);
+  final Matrix4 outer = new Matrix4.outer(v, v);
   Matrix4 r = new Matrix4.zero();
   r = r - outer;
-  Vector3 scaledNormal = (planeNormal.scaled(dot3(planePoint, planeNormal)));
-  Vector4 T = new Vector4(scaledNormal.storage[0], scaledNormal.storage[1],
-      scaledNormal.storage[2], 1.0);
+  final Vector3 scaledNormal =
+      (planeNormal.scaled(dot3(planePoint, planeNormal)));
+  final Vector4 T = new Vector4(scaledNormal.storage[0],
+      scaledNormal.storage[1], scaledNormal.storage[2], 1.0);
   r.setColumn(3, T);
   return r;
 }
@@ -275,16 +277,15 @@
 /// Returns a transformation matrix that transforms points by reflecting
 /// them through the plane specified with [planeNormal] and [planePoint].
 Matrix4 makePlaneReflection(Vector3 planeNormal, Vector3 planePoint) {
-  Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
+  final Vector4 v = new Vector4(planeNormal.storage[0], planeNormal.storage[1],
       planeNormal.storage[2], 0.0);
-  Matrix4 outer = new Matrix4.outer(v, v);
-  outer.scale(2.0);
+  final Matrix4 outer = new Matrix4.outer(v, v)..scale(2.0);
   Matrix4 r = new Matrix4.zero();
   r = r - outer;
-  double scale = 2.0 * planePoint.dot(planeNormal);
-  Vector3 scaledNormal = (planeNormal.scaled(scale));
-  Vector4 T = new Vector4(scaledNormal.storage[0], scaledNormal.storage[1],
-      scaledNormal.storage[2], 1.0);
+  final double scale = 2.0 * planePoint.dot(planeNormal);
+  final Vector3 scaledNormal = (planeNormal.scaled(scale));
+  final Vector4 T = new Vector4(scaledNormal.storage[0],
+      scaledNormal.storage[1], scaledNormal.storage[2], 1.0);
   r.setColumn(3, T);
   return r;
 }
@@ -333,19 +334,21 @@
   }
 
   // Copy camera matrix.
-  Matrix4 invertedCameraMatrix = new Matrix4.copy(cameraMatrix);
+  final Matrix4 invertedCameraMatrix = new Matrix4.copy(cameraMatrix);
   // Invert the camera matrix.
   invertedCameraMatrix.invert();
   // Determine intersection point.
-  Vector4 v = new Vector4(pickX, pickY, pickZ, 1.0);
+  final Vector4 v =
+      new Vector4(pickX.toDouble(), pickY.toDouble(), pickZ.toDouble(), 1.0);
   invertedCameraMatrix.transform(v);
   if (v.w == 0.0) {
     return false;
   }
-  double invW = 1.0 / v.w;
-  pickWorld.x = v.x * invW;
-  pickWorld.y = v.y * invW;
-  pickWorld.z = v.z * invW;
+  final double invW = 1.0 / v.w;
+  pickWorld
+    ..x = v.x * invW
+    ..y = v.y * invW
+    ..z = v.z * invW;
 
   return true;
 }
diff --git a/pub/vector_math/lib/src/vector_math_64/plane.dart b/pub/vector_math/lib/src/vector_math_64/plane.dart
index c11d87d..2ad5b8a 100644
--- a/pub/vector_math/lib/src/vector_math_64/plane.dart
+++ b/pub/vector_math/lib/src/vector_math_64/plane.dart
@@ -11,25 +11,26 @@
   /// Find the intersection point between the three planes [a], [b] and [c] and
   /// copy it into [result].
   static void intersection(Plane a, Plane b, Plane c, Vector3 result) {
-    final cross = new Vector3.zero();
+    final Vector3 cross = new Vector3.zero();
 
     b.normal.crossInto(c.normal, cross);
 
-    final f = -a.normal.dot(cross);
+    final double f = -a.normal.dot(cross);
 
-    final v1 = cross.scaled(a.constant);
+    final Vector3 v1 = cross.scaled(a.constant);
 
     c.normal.crossInto(a.normal, cross);
 
-    final v2 = cross.scaled(b.constant);
+    final Vector3 v2 = cross.scaled(b.constant);
 
     a.normal.crossInto(b.normal, cross);
 
-    final v3 = cross.scaled(c.constant);
+    final Vector3 v3 = cross.scaled(c.constant);
 
-    result.x = (v1.x + v2.x + v3.x) / f;
-    result.y = (v1.y + v2.y + v3.y) / f;
-    result.z = (v1.z + v2.z + v3.z) / f;
+    result
+      ..x = (v1.x + v2.x + v3.x) / f
+      ..y = (v1.y + v2.y + v3.y) / f
+      ..z = (v1.z + v2.z + v3.z) / f;
   }
 
   Vector3 get normal => _normal;
@@ -63,12 +64,10 @@
   }
 
   void normalize() {
-    var inverseLength = 1.0 / normal.length;
+    final double inverseLength = 1.0 / normal.length;
     _normal.scale(inverseLength);
     _constant *= inverseLength;
   }
 
-  double distanceToVector3(Vector3 point) {
-    return _normal.dot(point) + _constant;
-  }
+  double distanceToVector3(Vector3 point) => _normal.dot(point) + _constant;
 }
diff --git a/pub/vector_math/lib/src/vector_math_64/quad.dart b/pub/vector_math/lib/src/vector_math_64/quad.dart
index ab5da13..ea605f7 100644
--- a/pub/vector_math/lib/src/vector_math_64/quad.dart
+++ b/pub/vector_math/lib/src/vector_math_64/quad.dart
@@ -54,7 +54,7 @@
 
   /// Copy the normal of [this] into [normal].
   void copyNormalInto(Vector3 normal) {
-    final v0 = _point0.clone()..sub(_point1);
+    final Vector3 v0 = _point0.clone()..sub(_point1);
     normal
       ..setFrom(_point2)
       ..sub(_point1)
@@ -74,10 +74,11 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    t.transform3(_point0);
-    t.transform3(_point1);
-    t.transform3(_point2);
-    t.transform3(_point3);
+    t
+      ..transform3(_point0)
+      ..transform3(_point1)
+      ..transform3(_point2)
+      ..transform3(_point3);
   }
 
   /// Translate [this] by [offset].
diff --git a/pub/vector_math/lib/src/vector_math_64/quaternion.dart b/pub/vector_math/lib/src/vector_math_64/quaternion.dart
index 22126ec..5681555 100644
--- a/pub/vector_math/lib/src/vector_math_64/quaternion.dart
+++ b/pub/vector_math/lib/src/vector_math_64/quaternion.dart
@@ -64,7 +64,7 @@
 
   /// Constructs a quaternion with a random rotation. The random number
   /// generator [rn] is used to generate the random numbers for the rotation.
-  factory Quaternion.random(Math.Random rn) =>
+  factory Quaternion.random(math.Random rn) =>
       new Quaternion._()..setRandom(rn);
 
   /// Constructs a quaternion set to the identity quaternion.
@@ -93,7 +93,7 @@
 
   /// Copy [source] into [this].
   void setFrom(Quaternion source) {
-    final sourceStorage = source._qStorage;
+    final Float64List sourceStorage = source._qStorage;
     _qStorage[0] = sourceStorage[0];
     _qStorage[1] = sourceStorage[1];
     _qStorage[2] = sourceStorage[2];
@@ -110,36 +110,36 @@
 
   /// Set the quaternion with rotation of [radians] around [axis].
   void setAxisAngle(Vector3 axis, double radians) {
-    final len = axis.length;
+    final double len = axis.length;
     if (len == 0.0) {
       return;
     }
-    final halfSin = Math.sin(radians * 0.5) / len;
-    final axisStorage = axis.storage;
+    final double halfSin = math.sin(radians * 0.5) / len;
+    final Float64List axisStorage = axis.storage;
     _qStorage[0] = axisStorage[0] * halfSin;
     _qStorage[1] = axisStorage[1] * halfSin;
     _qStorage[2] = axisStorage[2] * halfSin;
-    _qStorage[3] = Math.cos(radians * 0.5);
+    _qStorage[3] = math.cos(radians * 0.5);
   }
 
   /// Set the quaternion with rotation from a rotation matrix [rotationMatrix].
   void setFromRotation(Matrix3 rotationMatrix) {
-    final rotationMatrixStorage = rotationMatrix.storage;
-    final trace = rotationMatrix.trace();
+    final Float64List rotationMatrixStorage = rotationMatrix.storage;
+    final double trace = rotationMatrix.trace();
     if (trace > 0.0) {
-      var s = Math.sqrt(trace + 1.0);
+      double s = math.sqrt(trace + 1.0);
       _qStorage[3] = s * 0.5;
       s = 0.5 / s;
       _qStorage[0] = (rotationMatrixStorage[5] - rotationMatrixStorage[7]) * s;
       _qStorage[1] = (rotationMatrixStorage[6] - rotationMatrixStorage[2]) * s;
       _qStorage[2] = (rotationMatrixStorage[1] - rotationMatrixStorage[3]) * s;
     } else {
-      var i = rotationMatrixStorage[0] < rotationMatrixStorage[4]
+      final int i = rotationMatrixStorage[0] < rotationMatrixStorage[4]
           ? (rotationMatrixStorage[4] < rotationMatrixStorage[8] ? 2 : 1)
           : (rotationMatrixStorage[0] < rotationMatrixStorage[8] ? 2 : 0);
-      var j = (i + 1) % 3;
-      var k = (i + 2) % 3;
-      var s = Math.sqrt(rotationMatrixStorage[rotationMatrix.index(i, i)] -
+      final int j = (i + 1) % 3;
+      final int k = (i + 2) % 3;
+      double s = math.sqrt(rotationMatrixStorage[rotationMatrix.index(i, i)] -
           rotationMatrixStorage[rotationMatrix.index(j, j)] -
           rotationMatrixStorage[rotationMatrix.index(k, k)] +
           1.0);
@@ -158,16 +158,16 @@
   }
 
   void setFromTwoVectors(Vector3 a, Vector3 b) {
-    Vector3 v1 = a.normalized();
-    Vector3 v2 = b.normalized();
+    final Vector3 v1 = a.normalized();
+    final Vector3 v2 = b.normalized();
 
-    double c = v1.dot(v2);
-    double angle = Math.acos(c);
+    final double c = v1.dot(v2);
+    double angle = math.acos(c);
     Vector3 axis = v1.cross(v2);
 
     if ((1.0 + c).abs() < 0.0005) {
       // c \approx -1 indicates 180 degree rotation
-      angle = Math.PI;
+      angle = math.PI;
 
       // a and b are parallel in opposite directions. We need any
       // vector as our rotation axis that is perpendicular.
@@ -190,18 +190,18 @@
 
   /// Set the quaternion to a random rotation. The random number generator [rn]
   /// is used to generate the random numbers for the rotation.
-  void setRandom(Math.Random rn) {
+  void setRandom(math.Random rn) {
     // From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III,
     // pg. 124-132.
-    final x0 = rn.nextDouble();
-    final r1 = Math.sqrt(1.0 - x0);
-    final r2 = Math.sqrt(x0);
-    final t1 = Math.PI * 2.0 * rn.nextDouble();
-    final t2 = Math.PI * 2.0 * rn.nextDouble();
-    final c1 = Math.cos(t1);
-    final s1 = Math.sin(t1);
-    final c2 = Math.cos(t2);
-    final s2 = Math.sin(t2);
+    final double x0 = rn.nextDouble();
+    final double r1 = math.sqrt(1.0 - x0);
+    final double r2 = math.sqrt(x0);
+    final double t1 = math.PI * 2.0 * rn.nextDouble();
+    final double t2 = math.PI * 2.0 * rn.nextDouble();
+    final double c1 = math.cos(t1);
+    final double s1 = math.sin(t1);
+    final double c2 = math.cos(t2);
+    final double s2 = math.sin(t2);
     _qStorage[0] = s1 * r1;
     _qStorage[1] = c1 * r1;
     _qStorage[2] = s2 * r2;
@@ -211,19 +211,19 @@
   /// Set the quaternion to the time derivative of [q] with angular velocity
   /// [omega].
   void setDQ(Quaternion q, Vector3 omega) {
-    final qStorage = q._qStorage;
-    final omegaStorage = omega.storage;
-    final qx = qStorage[0];
-    final qy = qStorage[1];
-    final qz = qStorage[2];
-    final qw = qStorage[3];
-    final ox = omegaStorage[0];
-    final oy = omegaStorage[1];
-    final oz = omegaStorage[2];
-    final _x = ox * qw + oy * qz - oz * qy;
-    final _y = oy * qw + oz * qx - ox * qz;
-    final _z = oz * qw + ox * qy - oy * qx;
-    final _w = -ox * qx - oy * qy - oz * qz;
+    final Float64List qStorage = q._qStorage;
+    final Float64List omegaStorage = omega.storage;
+    final double qx = qStorage[0];
+    final double qy = qStorage[1];
+    final double qz = qStorage[2];
+    final double qw = qStorage[3];
+    final double ox = omegaStorage[0];
+    final double oy = omegaStorage[1];
+    final double oz = omegaStorage[2];
+    final double _x = ox * qw + oy * qz - oz * qy;
+    final double _y = oy * qw + oz * qx - ox * qz;
+    final double _z = oz * qw + ox * qy - oy * qx;
+    final double _w = -ox * qx - oy * qy - oz * qz;
     _qStorage[0] = _x * 0.5;
     _qStorage[1] = _y * 0.5;
     _qStorage[2] = _z * 0.5;
@@ -232,15 +232,15 @@
 
   /// Set quaternion with rotation of [yaw], [pitch] and [roll].
   void setEuler(double yaw, double pitch, double roll) {
-    final halfYaw = yaw * 0.5;
-    final halfPitch = pitch * 0.5;
-    final halfRoll = roll * 0.5;
-    final cosYaw = Math.cos(halfYaw);
-    final sinYaw = Math.sin(halfYaw);
-    final cosPitch = Math.cos(halfPitch);
-    final sinPitch = Math.sin(halfPitch);
-    final cosRoll = Math.cos(halfRoll);
-    final sinRoll = Math.sin(halfRoll);
+    final double halfYaw = yaw * 0.5;
+    final double halfPitch = pitch * 0.5;
+    final double halfRoll = roll * 0.5;
+    final double cosYaw = math.cos(halfYaw);
+    final double sinYaw = math.sin(halfYaw);
+    final double cosPitch = math.cos(halfPitch);
+    final double sinPitch = math.sin(halfPitch);
+    final double cosRoll = math.cos(halfRoll);
+    final double sinRoll = math.sin(halfRoll);
     _qStorage[0] = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
     _qStorage[1] = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
     _qStorage[2] = sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw;
@@ -249,11 +249,11 @@
 
   /// Normalize [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _qStorage[0] *= d;
     _qStorage[1] *= d;
     _qStorage[2] *= d;
@@ -270,7 +270,7 @@
 
   /// Invert [this].
   void inverse() {
-    final l = 1.0 / length2;
+    final double l = 1.0 / length2;
     _qStorage[3] = _qStorage[3] * l;
     _qStorage[2] = -_qStorage[2] * l;
     _qStorage[1] = -_qStorage[1] * l;
@@ -287,36 +287,36 @@
   Quaternion inverted() => clone()..inverse();
 
   /// [radians] of rotation around the [axis] of the rotation.
-  double get radians => 2.0 * Math.acos(_qStorage[3]);
+  double get radians => 2.0 * math.acos(_qStorage[3]);
 
   /// [axis] of rotation.
   Vector3 get axis {
-    final den = 1.0 - (_qStorage[3] * _qStorage[3]);
+    final double den = 1.0 - (_qStorage[3] * _qStorage[3]);
     if (den < 0.0005) {
       // 0-angle rotation, so axis does not matter
       return new Vector3.zero();
     }
 
-    final scale = 1.0 / Math.sqrt(den);
+    final double scale = 1.0 / math.sqrt(den);
     return new Vector3(
         _qStorage[0] * scale, _qStorage[1] * scale, _qStorage[2] * scale);
   }
 
   /// Length squared.
   double get length2 {
-    final x = _qStorage[0];
-    final y = _qStorage[1];
-    final z = _qStorage[2];
-    final w = _qStorage[3];
+    final double x = _qStorage[0];
+    final double y = _qStorage[1];
+    final double z = _qStorage[2];
+    final double w = _qStorage[3];
     return (x * x) + (y * y) + (z * z) + (w * w);
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Returns a copy of [v] rotated by quaternion.
   Vector3 rotated(Vector3 v) {
-    final out = v.clone();
+    final Vector3 out = v.clone();
     rotate(out);
     return out;
   }
@@ -324,22 +324,22 @@
   /// Rotates [v] by [this].
   Vector3 rotate(Vector3 v) {
     // conjugate(this) * [v,0] * this
-    final _w = _qStorage[3];
-    final _z = _qStorage[2];
-    final _y = _qStorage[1];
-    final _x = _qStorage[0];
-    final tiw = _w;
-    final tiz = -_z;
-    final tiy = -_y;
-    final tix = -_x;
-    final tx = tiw * v.x + tix * 0.0 + tiy * v.z - tiz * v.y;
-    final ty = tiw * v.y + tiy * 0.0 + tiz * v.x - tix * v.z;
-    final tz = tiw * v.z + tiz * 0.0 + tix * v.y - tiy * v.x;
-    final tw = tiw * 0.0 - tix * v.x - tiy * v.y - tiz * v.z;
-    final result_x = tw * _x + tx * _w + ty * _z - tz * _y;
-    final result_y = tw * _y + ty * _w + tz * _x - tx * _z;
-    final result_z = tw * _z + tz * _w + tx * _y - ty * _x;
-    final vStorage = v.storage;
+    final double _w = _qStorage[3];
+    final double _z = _qStorage[2];
+    final double _y = _qStorage[1];
+    final double _x = _qStorage[0];
+    final double tiw = _w;
+    final double tiz = -_z;
+    final double tiy = -_y;
+    final double tix = -_x;
+    final double tx = tiw * v.x + tix * 0.0 + tiy * v.z - tiz * v.y;
+    final double ty = tiw * v.y + tiy * 0.0 + tiz * v.x - tix * v.z;
+    final double tz = tiw * v.z + tiz * 0.0 + tix * v.y - tiy * v.x;
+    final double tw = tiw * 0.0 - tix * v.x - tiy * v.y - tiz * v.z;
+    final double result_x = tw * _x + tx * _w + ty * _z - tz * _y;
+    final double result_y = tw * _y + ty * _w + tz * _x - tx * _z;
+    final double result_z = tw * _z + tz * _w + tx * _y - ty * _x;
+    final Float64List vStorage = v.storage;
     vStorage[2] = result_z;
     vStorage[1] = result_y;
     vStorage[0] = result_x;
@@ -348,7 +348,7 @@
 
   /// Add [arg] to [this].
   void add(Quaternion arg) {
-    final argStorage = arg._qStorage;
+    final Float64List argStorage = arg._qStorage;
     _qStorage[0] = _qStorage[0] + argStorage[0];
     _qStorage[1] = _qStorage[1] + argStorage[1];
     _qStorage[2] = _qStorage[2] + argStorage[2];
@@ -357,7 +357,7 @@
 
   /// Subtracts [arg] from [this].
   void sub(Quaternion arg) {
-    final argStorage = arg._qStorage;
+    final Float64List argStorage = arg._qStorage;
     _qStorage[0] = _qStorage[0] - argStorage[0];
     _qStorage[1] = _qStorage[1] - argStorage[1];
     _qStorage[2] = _qStorage[2] - argStorage[2];
@@ -377,15 +377,15 @@
 
   /// [this] rotated by [other].
   Quaternion operator *(Quaternion other) {
-    double _w = _qStorage[3];
-    double _z = _qStorage[2];
-    double _y = _qStorage[1];
-    double _x = _qStorage[0];
-    final otherStorage = other._qStorage;
-    double ow = otherStorage[3];
-    double oz = otherStorage[2];
-    double oy = otherStorage[1];
-    double ox = otherStorage[0];
+    final double _w = _qStorage[3];
+    final double _z = _qStorage[2];
+    final double _y = _qStorage[1];
+    final double _x = _qStorage[0];
+    final Float64List otherStorage = other._qStorage;
+    final double ow = otherStorage[3];
+    final double oz = otherStorage[2];
+    final double oy = otherStorage[1];
+    final double ox = otherStorage[0];
     return new Quaternion(
         _w * ox + _x * ow + _y * oz - _z * oy,
         _w * oy + _y * ow + _z * ox - _x * oz,
@@ -416,32 +416,32 @@
   /// Set [rotationMatrix] to a rotation matrix containing the same rotation as
   /// [this].
   Matrix3 copyRotationInto(Matrix3 rotationMatrix) {
-    final d = length2;
+    final double d = length2;
     assert(d != 0.0);
-    final s = 2.0 / d;
+    final double s = 2.0 / d;
 
-    final _x = _qStorage[0];
-    final _y = _qStorage[1];
-    final _z = _qStorage[2];
-    final _w = _qStorage[3];
+    final double _x = _qStorage[0];
+    final double _y = _qStorage[1];
+    final double _z = _qStorage[2];
+    final double _w = _qStorage[3];
 
-    final xs = _x * s;
-    final ys = _y * s;
-    final zs = _z * s;
+    final double xs = _x * s;
+    final double ys = _y * s;
+    final double zs = _z * s;
 
-    final wx = _w * xs;
-    final wy = _w * ys;
-    final wz = _w * zs;
+    final double wx = _w * xs;
+    final double wy = _w * ys;
+    final double wz = _w * zs;
 
-    final xx = _x * xs;
-    final xy = _x * ys;
-    final xz = _x * zs;
+    final double xx = _x * xs;
+    final double xy = _x * ys;
+    final double xz = _x * zs;
 
-    final yy = _y * ys;
-    final yz = _y * zs;
-    final zz = _z * zs;
+    final double yy = _y * ys;
+    final double yz = _y * zs;
+    final double zz = _z * zs;
 
-    final rotationMatrixStorage = rotationMatrix.storage;
+    final Float64List rotationMatrixStorage = rotationMatrix.storage;
     rotationMatrixStorage[0] = 1.0 - (yy + zz); // column 0
     rotationMatrixStorage[1] = xy + wz;
     rotationMatrixStorage[2] = xz - wy;
@@ -455,22 +455,23 @@
   }
 
   /// Printable string.
+  @override
   String toString() => '${_qStorage[0]}, ${_qStorage[1]},'
       ' ${_qStorage[2]} @ ${_qStorage[3]}';
 
   /// Relative error between [this] and [correct].
   double relativeError(Quaternion correct) {
-    final diff = correct - this;
-    final norm_diff = diff.length;
-    final correct_norm = correct.length;
+    final Quaternion diff = correct - this;
+    final double norm_diff = diff.length;
+    final double correct_norm = correct.length;
     return norm_diff / correct_norm;
   }
 
   /// Absolute error between [this] and [correct].
   double absoluteError(Quaternion correct) {
-    final this_norm = length;
-    final correct_norm = correct.length;
-    final norm_diff = (this_norm - correct_norm).abs();
+    final double this_norm = length;
+    final double correct_norm = correct.length;
+    final double norm_diff = (this_norm - correct_norm).abs();
     return norm_diff;
   }
 }
diff --git a/pub/vector_math/lib/src/vector_math_64/ray.dart b/pub/vector_math/lib/src/vector_math_64/ray.dart
index afdcdb9..d79e6dc 100644
--- a/pub/vector_math/lib/src/vector_math_64/ray.dart
+++ b/pub/vector_math/lib/src/vector_math_64/ray.dart
@@ -51,19 +51,19 @@
   /// Return the distance from the origin of [this] to the intersection with
   /// [other] if [this] intersects with [other], or null if the don't intersect.
   double intersectsWithSphere(Sphere other) {
-    final r = other._radius;
-    final r2 = r * r;
-    final l = other._center.clone()..sub(_origin);
-    final s = l.dot(_direction);
-    final l2 = l.dot(l);
+    final double r = other._radius;
+    final double r2 = r * r;
+    final Vector3 l = other._center.clone()..sub(_origin);
+    final double s = l.dot(_direction);
+    final double l2 = l.dot(l);
     if (s < 0 && l2 > r2) {
       return null;
     }
-    final m2 = l2 - s * s;
+    final double m2 = l2 - s * s;
     if (m2 > r2) {
       return null;
     }
-    final q = Math.sqrt(r2 - m2);
+    final double q = math.sqrt(r2 - m2);
 
     return (l2 > r2) ? s - q : s + q;
   }
@@ -71,20 +71,20 @@
   // Some varaibles that are used for intersectsWithTriangle and
   // intersectsWithQuad. The performance is better in Dart and JS if we avoid
   // to create temporary instance over and over. Also reduce GC.
-  static final _e1 = new Vector3.zero();
-  static final _e2 = new Vector3.zero();
-  static final _q = new Vector3.zero();
-  static final _s = new Vector3.zero();
-  static final _r = new Vector3.zero();
+  static final Vector3 _e1 = new Vector3.zero();
+  static final Vector3 _e2 = new Vector3.zero();
+  static final Vector3 _q = new Vector3.zero();
+  static final Vector3 _s = new Vector3.zero();
+  static final Vector3 _r = new Vector3.zero();
 
   /// Return the distance from the origin of [this] to the intersection with
   /// [other] if [this] intersects with [other], or null if the don't intersect.
   double intersectsWithTriangle(Triangle other) {
     const double EPSILON = 10e-6;
 
-    final point0 = other._point0;
-    final point1 = other._point1;
-    final point2 = other._point2;
+    final Vector3 point0 = other._point0;
+    final Vector3 point1 = other._point1;
+    final Vector3 point2 = other._point2;
 
     _e1
       ..setFrom(point1)
@@ -94,30 +94,30 @@
       ..sub(point0);
 
     _direction.crossInto(_e2, _q);
-    final a = _e1.dot(_q);
+    final double a = _e1.dot(_q);
 
     if (a > -EPSILON && a < EPSILON) {
       return null;
     }
 
-    final f = 1 / a;
+    final double f = 1 / a;
     _s
       ..setFrom(_origin)
       ..sub(point0);
-    final u = f * (_s.dot(_q));
+    final double u = f * (_s.dot(_q));
 
     if (u < 0.0) {
       return null;
     }
 
     _s.crossInto(_e1, _r);
-    final v = f * (_direction.dot(_r));
+    final double v = f * (_direction.dot(_r));
 
     if (v < -EPSILON || u + v > 1.0 + EPSILON) {
       return null;
     }
 
-    final t = f * (_e2.dot(_r));
+    final double t = f * (_e2.dot(_r));
 
     return t;
   }
@@ -128,9 +128,9 @@
     const double EPSILON = 10e-6;
 
     // First triangle
-    var point0 = other._point0;
-    var point1 = other._point1;
-    var point2 = other._point2;
+    Vector3 point0 = other._point0;
+    Vector3 point1 = other._point1;
+    Vector3 point2 = other._point2;
 
     _e1
       ..setFrom(point1)
@@ -140,21 +140,21 @@
       ..sub(point0);
 
     _direction.crossInto(_e2, _q);
-    final a0 = _e1.dot(_q);
+    final double a0 = _e1.dot(_q);
 
     if (!(a0 > -EPSILON && a0 < EPSILON)) {
-      final f = 1 / a0;
+      final double f = 1 / a0;
       _s
         ..setFrom(_origin)
         ..sub(point0);
-      final u = f * (_s.dot(_q));
+      final double u = f * (_s.dot(_q));
 
       if (u >= 0.0) {
         _s.crossInto(_e1, _r);
-        final v = f * (_direction.dot(_r));
+        final double v = f * (_direction.dot(_r));
 
         if (!(v < -EPSILON || u + v > 1.0 + EPSILON)) {
-          final t = f * (_e2.dot(_r));
+          final double t = f * (_e2.dot(_r));
 
           return t;
         }
@@ -174,21 +174,21 @@
       ..sub(point0);
 
     _direction.crossInto(_e2, _q);
-    final a1 = _e1.dot(_q);
+    final double a1 = _e1.dot(_q);
 
     if (!(a1 > -EPSILON && a1 < EPSILON)) {
-      final f = 1 / a1;
+      final double f = 1 / a1;
       _s
         ..setFrom(_origin)
         ..sub(point0);
-      final u = f * (_s.dot(_q));
+      final double u = f * (_s.dot(_q));
 
       if (u >= 0.0) {
         _s.crossInto(_e1, _r);
-        final v = f * (_direction.dot(_r));
+        final double v = f * (_direction.dot(_r));
 
         if (!(v < -EPSILON || u + v > 1.0 + EPSILON)) {
-          final t = f * (_e2.dot(_r));
+          final double t = f * (_e2.dot(_r));
 
           return t;
         }
@@ -201,23 +201,23 @@
   /// Return the distance from the origin of [this] to the intersection with
   /// [other] if [this] intersects with [other], or null if the don't intersect.
   double intersectsWithAabb3(Aabb3 other) {
-    final otherMin = other.min;
-    final otherMax = other.max;
+    final Vector3 otherMin = other.min;
+    final Vector3 otherMax = other.max;
 
-    var tNear = -double.MAX_FINITE;
-    var tFar = double.MAX_FINITE;
+    double tNear = -double.MAX_FINITE;
+    double tFar = double.MAX_FINITE;
 
-    for (var i = 0; i < 3; ++i) {
+    for (int i = 0; i < 3; ++i) {
       if (_direction[i] == 0.0) {
         if (_origin[i] < otherMin[i] || _origin[i] > otherMax[i]) {
           return null;
         }
       } else {
-        var t1 = (otherMin[i] - _origin[i]) / _direction[i];
-        var t2 = (otherMax[i] - _origin[i]) / _direction[i];
+        double t1 = (otherMin[i] - _origin[i]) / _direction[i];
+        double t2 = (otherMax[i] - _origin[i]) / _direction[i];
 
         if (t1 > t2) {
-          final temp = t1;
+          final double temp = t1;
           t1 = t2;
           t2 = temp;
         }
diff --git a/pub/vector_math/lib/src/vector_math_64/sphere.dart b/pub/vector_math/lib/src/vector_math_64/sphere.dart
index 76737dc..e8f1707 100644
--- a/pub/vector_math/lib/src/vector_math_64/sphere.dart
+++ b/pub/vector_math/lib/src/vector_math_64/sphere.dart
@@ -38,18 +38,16 @@
   }
 
   /// Return if [this] contains [other].
-  bool containsVector3(Vector3 other) {
-    return other.distanceToSquared(center) < radius * radius;
-  }
+  bool containsVector3(Vector3 other) =>
+      other.distanceToSquared(center) < radius * radius;
 
   /// Return if [this] intersects with [other].
-  bool intersectsWithVector3(Vector3 other) {
-    return other.distanceToSquared(center) <= radius * radius;
-  }
+  bool intersectsWithVector3(Vector3 other) =>
+      other.distanceToSquared(center) <= radius * radius;
 
   /// Return if [this] intersects with [other].
   bool intersectsWithSphere(Sphere other) {
-    var radiusSum = radius + other.radius;
+    final double radiusSum = radius + other.radius;
 
     return other.center.distanceToSquared(center) <= (radiusSum * radiusSum);
   }
diff --git a/pub/vector_math/lib/src/vector_math_64/third_party/noise.dart b/pub/vector_math/lib/src/vector_math_64/third_party/noise.dart
index bb1b81f..60be2ea 100644
--- a/pub/vector_math/lib/src/vector_math_64/third_party/noise.dart
+++ b/pub/vector_math/lib/src/vector_math_64/third_party/noise.dart
@@ -27,54 +27,54 @@
  */
 
 class SimplexNoise {
-  static final _grad3 = <List<double>>[
-    [1.0, 1.0, 0.0],
-    [-1.0, 1.0, 0.0],
-    [1.0, -1.0, 0.0],
-    [-1.0, -1.0, 0.0],
-    [1.0, 0.0, 1.0],
-    [-1.0, 0.0, 1.0],
-    [1.0, 0.0, -1.0],
-    [-1.0, 0.0, -1.0],
-    [0.0, 1.0, 1.0],
-    [0.0, -1.0, 1.0],
-    [0.0, 1.0, -1.0],
-    [0.0, -1.0, -1.0]
+  static final List<List<double>> _grad3 = <List<double>>[
+    <double>[1.0, 1.0, 0.0],
+    <double>[-1.0, 1.0, 0.0],
+    <double>[1.0, -1.0, 0.0],
+    <double>[-1.0, -1.0, 0.0],
+    <double>[1.0, 0.0, 1.0],
+    <double>[-1.0, 0.0, 1.0],
+    <double>[1.0, 0.0, -1.0],
+    <double>[-1.0, 0.0, -1.0],
+    <double>[0.0, 1.0, 1.0],
+    <double>[0.0, -1.0, 1.0],
+    <double>[0.0, 1.0, -1.0],
+    <double>[0.0, -1.0, -1.0]
   ];
 
-  static final _grad4 = <List<double>>[
-    [0.0, 1.0, 1.0, 1.0],
-    [0.0, 1.0, 1.0, -1.0],
-    [0.0, 1.0, -1.0, 1.0],
-    [0.0, 1.0, -1.0, -1.0],
-    [0.0, -1.0, 1.0, 1.0],
-    [0.0, -1.0, 1.0, -1.0],
-    [0.0, -1.0, -1.0, 1.0],
-    [0.0, -1.0, -1.0, -1.0],
-    [1.0, 0.0, 1.0, 1.0],
-    [1.0, 0.0, 1.0, -1.0],
-    [1.0, 0.0, -1.0, 1.0],
-    [1.0, 0.0, -1.0, -1.0],
-    [-1.0, 0.0, 1.0, 1.0],
-    [-1.0, 0.0, 1.0, -1.0],
-    [-1.0, 0.0, -1.0, 1.0],
-    [-1.0, 0.0, -1.0, -1.0],
-    [1.0, 1.0, 0.0, 1.0],
-    [1.0, 1.0, 0.0, -1.0],
-    [1.0, -1.0, 0.0, 1.0],
-    [1.0, -1.0, 0.0, -1.0],
-    [-1.0, 1.0, 0.0, 1.0],
-    [-1.0, 1.0, 0.0, -1.0],
-    [-1.0, -1.0, 0.0, 1.0],
-    [-1.0, -1.0, 0.0, -1.0],
-    [1.0, 1.0, 1.0, 0.0],
-    [1.0, 1.0, -1.0, 0.0],
-    [1.0, -1.0, 1.0, 0.0],
-    [1.0, -1.0, -1.0, 0.0],
-    [-1.0, 1.0, 1.0, 0.0],
-    [-1.0, 1.0, -1.0, 0.0],
-    [-1.0, -1.0, 1.0, 0.0],
-    [-1.0, -1.0, -1.0, 0.0]
+  static final List<List<double>> _grad4 = <List<double>>[
+    <double>[0.0, 1.0, 1.0, 1.0],
+    <double>[0.0, 1.0, 1.0, -1.0],
+    <double>[0.0, 1.0, -1.0, 1.0],
+    <double>[0.0, 1.0, -1.0, -1.0],
+    <double>[0.0, -1.0, 1.0, 1.0],
+    <double>[0.0, -1.0, 1.0, -1.0],
+    <double>[0.0, -1.0, -1.0, 1.0],
+    <double>[0.0, -1.0, -1.0, -1.0],
+    <double>[1.0, 0.0, 1.0, 1.0],
+    <double>[1.0, 0.0, 1.0, -1.0],
+    <double>[1.0, 0.0, -1.0, 1.0],
+    <double>[1.0, 0.0, -1.0, -1.0],
+    <double>[-1.0, 0.0, 1.0, 1.0],
+    <double>[-1.0, 0.0, 1.0, -1.0],
+    <double>[-1.0, 0.0, -1.0, 1.0],
+    <double>[-1.0, 0.0, -1.0, -1.0],
+    <double>[1.0, 1.0, 0.0, 1.0],
+    <double>[1.0, 1.0, 0.0, -1.0],
+    <double>[1.0, -1.0, 0.0, 1.0],
+    <double>[1.0, -1.0, 0.0, -1.0],
+    <double>[-1.0, 1.0, 0.0, 1.0],
+    <double>[-1.0, 1.0, 0.0, -1.0],
+    <double>[-1.0, -1.0, 0.0, 1.0],
+    <double>[-1.0, -1.0, 0.0, -1.0],
+    <double>[1.0, 1.0, 1.0, 0.0],
+    <double>[1.0, 1.0, -1.0, 0.0],
+    <double>[1.0, -1.0, 1.0, 0.0],
+    <double>[1.0, -1.0, -1.0, 0.0],
+    <double>[-1.0, 1.0, 1.0, 0.0],
+    <double>[-1.0, 1.0, -1.0, 0.0],
+    <double>[-1.0, -1.0, 1.0, 0.0],
+    <double>[-1.0, -1.0, -1.0, 0.0]
   ];
 
   // To remove the need for index wrapping, double the permutation table length
@@ -82,12 +82,12 @@
   List<int> _permMod12;
 
   // Skewing and unskewing factors for 2, 3, and 4 dimensions
-  static final double _F2 = 0.5 * (Math.sqrt(3.0) - 1.0);
-  static final double _G2 = (3.0 - Math.sqrt(3.0)) / 6.0;
+  static final double _F2 = 0.5 * (math.sqrt(3.0) - 1.0);
+  static final double _G2 = (3.0 - math.sqrt(3.0)) / 6.0;
   static const double _F3 = 1.0 / 3.0;
   static const double _G3 = 1.0 / 6.0;
-  static final double _F4 = (Math.sqrt(5.0) - 1.0) / 4.0;
-  static final double _G4 = (5.0 - Math.sqrt(5.0)) / 20.0;
+  static final double _F4 = (math.sqrt(5.0) - 1.0) / 4.0;
+  static final double _G4 = (5.0 - math.sqrt(5.0)) / 20.0;
 
   double _dot2(List<double> g, double x, double y) => g[0] * x + g[1] * y;
 
@@ -97,29 +97,27 @@
   double _dot4(List<double> g, double x, double y, double z, double w) =>
       g[0] * x + g[1] * y + g[2] * z + g[3] * w;
 
-  SimplexNoise([Math.Random r]) {
-    if (r == null) {
-      r = new Math.Random();
-    }
-    List<int> p =
-        new List<int>.generate(256, (i) => r.nextInt(256), growable: false);
-    _perm = new List<int>.generate(p.length * 2, (i) => p[i % p.length],
+  SimplexNoise([math.Random r]) {
+    r ??= new math.Random();
+    final List<int> p =
+        new List<int>.generate(256, (_) => r.nextInt(256), growable: false);
+    _perm = new List<int>.generate(p.length * 2, (int i) => p[i % p.length],
         growable: false);
-    _permMod12 = new List<int>.generate(_perm.length, (i) => _perm[i] % 12,
+    _permMod12 = new List<int>.generate(_perm.length, (int i) => _perm[i] % 12,
         growable: false);
   }
 
   double noise2D(double xin, double yin) {
     double n0, n1, n2; // Noise contributions from the three corners
     // Skew the input space to determine which simplex cell we're in
-    double s = (xin + yin) * _F2; // Hairy factor for 2D
-    int i = (xin + s).floor();
-    int j = (yin + s).floor();
-    double t = (i + j) * _G2;
-    double X0 = i - t; // Unskew the cell origin back to (x,y) space
-    double Y0 = j - t;
-    double x0 = xin - X0; // The x,y distances from the cell origin
-    double y0 = yin - Y0;
+    final double s = (xin + yin) * _F2; // Hairy factor for 2D
+    final int i = (xin + s).floor();
+    final int j = (yin + s).floor();
+    final double t = (i + j) * _G2;
+    final double X0 = i - t; // Unskew the cell origin back to (x,y) space
+    final double Y0 = j - t;
+    final double x0 = xin - X0; // The x,y distances from the cell origin
+    final double y0 = yin - Y0;
     // For the 2D case, the simplex shape is an equilateral triangle.
     // Determine which simplex we are in.
     int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
@@ -134,19 +132,19 @@
     // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
     // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
     // c = (3-sqrt(3))/6
-    double x1 =
+    final double x1 =
         x0 - i1 + _G2; // Offsets for middle corner in (x,y) unskewed coords
-    double y1 = y0 - j1 + _G2;
-    double x2 = x0 -
+    final double y1 = y0 - j1 + _G2;
+    final double x2 = x0 -
         1.0 +
         2.0 * _G2; // Offsets for last corner in (x,y) unskewed coords
-    double y2 = y0 - 1.0 + 2.0 * _G2;
+    final double y2 = y0 - 1.0 + 2.0 * _G2;
     // Work out the hashed gradient indices of the three simplex corners
-    int ii = i & 255;
-    int jj = j & 255;
-    int gi0 = _permMod12[ii + _perm[jj]];
-    int gi1 = _permMod12[ii + i1 + _perm[jj + j1]];
-    int gi2 = _permMod12[ii + 1 + _perm[jj + 1]];
+    final int ii = i & 255;
+    final int jj = j & 255;
+    final int gi0 = _permMod12[ii + _perm[jj]];
+    final int gi1 = _permMod12[ii + i1 + _perm[jj + j1]];
+    final int gi2 = _permMod12[ii + 1 + _perm[jj + 1]];
     // Calculate the contribution from the three corners
     double t0 = 0.5 - x0 * x0 - y0 * y0;
     if (t0 < 0)
@@ -180,18 +178,18 @@
   double noise3D(double xin, double yin, double zin) {
     double n0, n1, n2, n3; // Noise contributions from the four corners
     // Skew the input space to determine which simplex cell we're in
-    double s =
+    final double s =
         (xin + yin + zin) * _F3; // Very nice and simple skew factor for 3D
-    int i = (xin + s).floor();
-    int j = (yin + s).floor();
-    int k = (zin + s).floor();
-    double t = (i + j + k) * _G3;
-    double X0 = i - t; // Unskew the cell origin back to (x,y,z) space
-    double Y0 = j - t;
-    double Z0 = k - t;
-    double x0 = xin - X0; // The x,y,z distances from the cell origin
-    double y0 = yin - Y0;
-    double z0 = zin - Z0;
+    final int i = (xin + s).floor();
+    final int j = (yin + s).floor();
+    final int k = (zin + s).floor();
+    final double t = (i + j + k) * _G3;
+    final double X0 = i - t; // Unskew the cell origin back to (x,y,z) space
+    final double Y0 = j - t;
+    final double Z0 = k - t;
+    final double x0 = xin - X0; // The x,y,z distances from the cell origin
+    final double y0 = yin - Y0;
+    final double z0 = zin - Z0;
     // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
     // Determine which simplex we are in.
     int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
@@ -252,25 +250,26 @@
     // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
     // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
     // c = 1/6.
-    double x1 = x0 - i1 + _G3; // Offsets for second corner in (x,y,z) coords
-    double y1 = y0 - j1 + _G3;
-    double z1 = z0 - k1 + _G3;
-    double x2 =
+    final double x1 =
+        x0 - i1 + _G3; // Offsets for second corner in (x,y,z) coords
+    final double y1 = y0 - j1 + _G3;
+    final double z1 = z0 - k1 + _G3;
+    final double x2 =
         x0 - i2 + 2.0 * _G3; // Offsets for third corner in (x,y,z) coords
-    double y2 = y0 - j2 + 2.0 * _G3;
-    double z2 = z0 - k2 + 2.0 * _G3;
-    double x3 =
+    final double y2 = y0 - j2 + 2.0 * _G3;
+    final double z2 = z0 - k2 + 2.0 * _G3;
+    final double x3 =
         x0 - 1.0 + 3.0 * _G3; // Offsets for last corner in (x,y,z) coords
-    double y3 = y0 - 1.0 + 3.0 * _G3;
-    double z3 = z0 - 1.0 + 3.0 * _G3;
+    final double y3 = y0 - 1.0 + 3.0 * _G3;
+    final double z3 = z0 - 1.0 + 3.0 * _G3;
     // Work out the hashed gradient indices of the four simplex corners
-    int ii = i & 255;
-    int jj = j & 255;
-    int kk = k & 255;
-    int gi0 = _permMod12[ii + _perm[jj + _perm[kk]]];
-    int gi1 = _permMod12[ii + i1 + _perm[jj + j1 + _perm[kk + k1]]];
-    int gi2 = _permMod12[ii + i2 + _perm[jj + j2 + _perm[kk + k2]]];
-    int gi3 = _permMod12[ii + 1 + _perm[jj + 1 + _perm[kk + 1]]];
+    final int ii = i & 255;
+    final int jj = j & 255;
+    final int kk = k & 255;
+    final int gi0 = _permMod12[ii + _perm[jj + _perm[kk]]];
+    final int gi1 = _permMod12[ii + i1 + _perm[jj + j1 + _perm[kk + k1]]];
+    final int gi2 = _permMod12[ii + i2 + _perm[jj + j2 + _perm[kk + k2]]];
+    final int gi3 = _permMod12[ii + 1 + _perm[jj + 1 + _perm[kk + 1]]];
     // Calculate the contribution from the four corners
     double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
     if (t0 < 0)
@@ -309,20 +308,20 @@
   double noise4D(double x, double y, double z, double w) {
     double n0, n1, n2, n3, n4; // Noise contributions from the five corners
     // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
-    double s = (x + y + z + w) * _F4; // Factor for 4D skewing
-    int i = (x + s).floor();
-    int j = (y + s).floor();
-    int k = (z + s).floor();
-    int l = (w + s).floor();
-    double t = (i + j + k + l) * _G4; // Factor for 4D unskewing
-    double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
-    double Y0 = j - t;
-    double Z0 = k - t;
-    double W0 = l - t;
-    double x0 = x - X0; // The x,y,z,w distances from the cell origin
-    double y0 = y - Y0;
-    double z0 = z - Z0;
-    double w0 = w - W0;
+    final double s = (x + y + z + w) * _F4; // Factor for 4D skewing
+    final int i = (x + s).floor();
+    final int j = (y + s).floor();
+    final int k = (z + s).floor();
+    final int l = (w + s).floor();
+    final double t = (i + j + k + l) * _G4; // Factor for 4D unskewing
+    final double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
+    final double Y0 = j - t;
+    final double Z0 = k - t;
+    final double W0 = l - t;
+    final double x0 = x - X0; // The x,y,z,w distances from the cell origin
+    final double y0 = y - Y0;
+    final double z0 = z - Z0;
+    final double w0 = w - W0;
     // For the 4D case, the simplex is a 4D shape I won't even try to describe.
     // To find out which of the 24 possible simplices we're in, we need to
     // determine the magnitude ordering of x0, y0, z0 and w0.
@@ -379,38 +378,39 @@
     k3 = rankz >= 1 ? 1 : 0;
     l3 = rankw >= 1 ? 1 : 0;
     // The fifth corner has all coordinate offsets = 1, so no need to compute that.
-    double x1 = x0 - i1 + _G4; // Offsets for second corner in (x,y,z,w) coords
-    double y1 = y0 - j1 + _G4;
-    double z1 = z0 - k1 + _G4;
-    double w1 = w0 - l1 + _G4;
-    double x2 =
+    final double x1 =
+        x0 - i1 + _G4; // Offsets for second corner in (x,y,z,w) coords
+    final double y1 = y0 - j1 + _G4;
+    final double z1 = z0 - k1 + _G4;
+    final double w1 = w0 - l1 + _G4;
+    final double x2 =
         x0 - i2 + 2.0 * _G4; // Offsets for third corner in (x,y,z,w) coords
-    double y2 = y0 - j2 + 2.0 * _G4;
-    double z2 = z0 - k2 + 2.0 * _G4;
-    double w2 = w0 - l2 + 2.0 * _G4;
-    double x3 =
+    final double y2 = y0 - j2 + 2.0 * _G4;
+    final double z2 = z0 - k2 + 2.0 * _G4;
+    final double w2 = w0 - l2 + 2.0 * _G4;
+    final double x3 =
         x0 - i3 + 3.0 * _G4; // Offsets for fourth corner in (x,y,z,w) coords
-    double y3 = y0 - j3 + 3.0 * _G4;
-    double z3 = z0 - k3 + 3.0 * _G4;
-    double w3 = w0 - l3 + 3.0 * _G4;
-    double x4 =
+    final double y3 = y0 - j3 + 3.0 * _G4;
+    final double z3 = z0 - k3 + 3.0 * _G4;
+    final double w3 = w0 - l3 + 3.0 * _G4;
+    final double x4 =
         x0 - 1.0 + 4.0 * _G4; // Offsets for last corner in (x,y,z,w) coords
-    double y4 = y0 - 1.0 + 4.0 * _G4;
-    double z4 = z0 - 1.0 + 4.0 * _G4;
-    double w4 = w0 - 1.0 + 4.0 * _G4;
+    final double y4 = y0 - 1.0 + 4.0 * _G4;
+    final double z4 = z0 - 1.0 + 4.0 * _G4;
+    final double w4 = w0 - 1.0 + 4.0 * _G4;
     // Work out the hashed gradient indices of the five simplex corners
-    int ii = i & 255;
-    int jj = j & 255;
-    int kk = k & 255;
-    int ll = l & 255;
-    int gi0 = _perm[ii + _perm[jj + _perm[kk + _perm[ll]]]] % 32;
-    int gi1 =
+    final int ii = i & 255;
+    final int jj = j & 255;
+    final int kk = k & 255;
+    final int ll = l & 255;
+    final int gi0 = _perm[ii + _perm[jj + _perm[kk + _perm[ll]]]] % 32;
+    final int gi1 =
         _perm[ii + i1 + _perm[jj + j1 + _perm[kk + k1 + _perm[ll + l1]]]] % 32;
-    int gi2 =
+    final int gi2 =
         _perm[ii + i2 + _perm[jj + j2 + _perm[kk + k2 + _perm[ll + l2]]]] % 32;
-    int gi3 =
+    final int gi3 =
         _perm[ii + i3 + _perm[jj + j3 + _perm[kk + k3 + _perm[ll + l3]]]] % 32;
-    int gi4 =
+    final int gi4 =
         _perm[ii + 1 + _perm[jj + 1 + _perm[kk + 1 + _perm[ll + 1]]]] % 32;
     // Calculate the contribution from the five corners
     double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
diff --git a/pub/vector_math/lib/src/vector_math_64/triangle.dart b/pub/vector_math/lib/src/vector_math_64/triangle.dart
index e41938e..9ea99b4 100644
--- a/pub/vector_math/lib/src/vector_math_64/triangle.dart
+++ b/pub/vector_math/lib/src/vector_math_64/triangle.dart
@@ -46,7 +46,7 @@
 
   /// Copy the normal of [this] into [normal].
   void copyNormalInto(Vector3 normal) {
-    final v0 = point0.clone()..sub(point1);
+    final Vector3 v0 = point0.clone()..sub(point1);
     normal
       ..setFrom(point2)
       ..sub(point1)
@@ -56,9 +56,7 @@
 
   /// Transform [this] by the transform [t].
   void transform(Matrix4 t) {
-    t.transform3(_point0);
-    t.transform3(_point1);
-    t.transform3(_point2);
+    t..transform3(_point0)..transform3(_point1)..transform3(_point2);
   }
 
   /// Translate [this] by [offset].
diff --git a/pub/vector_math/lib/src/vector_math_64/utilities.dart b/pub/vector_math/lib/src/vector_math_64/utilities.dart
index 3426ddf..ca46e00 100644
--- a/pub/vector_math/lib/src/vector_math_64/utilities.dart
+++ b/pub/vector_math/lib/src/vector_math_64/utilities.dart
@@ -5,39 +5,32 @@
 part of vector_math_64;
 
 /// Convert [radians] to degrees.
-double degrees(double radians) {
-  return radians * radians2Degrees;
-}
+double degrees(double radians) => radians * radians2Degrees;
 
 /// Convert [degrees] to radians.
-double radians(double degrees) {
-  return degrees * degrees2Radians;
-}
+double radians(double degrees) => degrees * degrees2Radians;
 
 /// Interpolate between [min] and [max] with the amount of [a] using a linear
 /// interpolation. The computation is equivalent to the GLSL function mix.
-double mix(double min, double max, double a) {
-  return min + a * (max - min);
-}
+double mix(double min, double max, double a) => min + a * (max - min);
 
 /// Do a smooth step (hermite interpolation) interpolation with [edge0] and
 /// [edge1] by [amount]. The computation is equivalent to the GLSL function
 /// smoothstep.
 double smoothStep(double edge0, double edge1, double amount) {
-  final t = ((amount - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
+  final double t =
+      ((amount - edge0) / (edge1 - edge0)).clamp(0.0, 1.0).toDouble();
 
   return t * t * (3.0 - 2.0 * t);
 }
 
 /// Do a catmull rom spline interpolation with [edge0], [edge1], [edge2] and
 /// [edge3] by [amount].
-double catmullRom(
-    double edge0, double edge1, double edge2, double edge3, double amount) {
-  return 0.5 *
-      ((2.0 * edge1) +
-          (-edge0 + edge2) * amount +
-          (2.0 * edge0 - 5.0 * edge1 + 4.0 * edge2 - edge3) *
-              (amount * amount) +
-          (-edge0 + 3.0 * edge1 - 3.0 * edge2 + edge3) *
-              (amount * amount * amount));
-}
+double catmullRom(double edge0, double edge1, double edge2, double edge3,
+        double amount) =>
+    0.5 *
+    ((2.0 * edge1) +
+        (-edge0 + edge2) * amount +
+        (2.0 * edge0 - 5.0 * edge1 + 4.0 * edge2 - edge3) * (amount * amount) +
+        (-edge0 + 3.0 * edge1 - 3.0 * edge2 + edge3) *
+            (amount * amount * amount));
diff --git a/pub/vector_math/lib/src/vector_math_64/vector.dart b/pub/vector_math/lib/src/vector_math_64/vector.dart
index 26cf85e..09e6428 100644
--- a/pub/vector_math/lib/src/vector_math_64/vector.dart
+++ b/pub/vector_math/lib/src/vector_math_64/vector.dart
@@ -20,41 +20,51 @@
 
 /// 2D cross product. double x vec2.
 void cross2A(double x, Vector2 y, Vector2 out) {
-  var tempy = x * y.x;
-  out.x = -x * y.y;
-  out.y = tempy;
+  final double tempy = x * y.x;
+  out
+    ..x = -x * y.y
+    ..y = tempy;
 }
 
 /// 2D cross product. vec2 x double.
 void cross2B(Vector2 x, double y, Vector2 out) {
-  var tempy = -y * x.x;
-  out.x = y * x.y;
-  out.y = tempy;
+  final double tempy = -y * x.x;
+  out
+    ..x = y * x.y
+    ..y = tempy;
 }
 
 /// Sets [u] and [v] to be two vectors orthogonal to each other and
 /// [planeNormal].
 void buildPlaneVectors(final Vector3 planeNormal, Vector3 u, Vector3 v) {
-  if (planeNormal.z.abs() > Math.SQRT1_2) {
+  if (planeNormal.z.abs() > math.SQRT1_2) {
     // choose u in y-z plane
-    double a = planeNormal.y * planeNormal.y + planeNormal.z * planeNormal.z;
-    double k = 1.0 / Math.sqrt(a);
-    u.x = 0.0;
-    u.y = -planeNormal.z * k;
-    u.z = planeNormal.y * k;
-    v.x = a * k;
-    v.y = -planeNormal[0] * (planeNormal[1] * k);
-    v.z = planeNormal[0] * (-planeNormal[2] * k);
+    final double a =
+        planeNormal.y * planeNormal.y + planeNormal.z * planeNormal.z;
+    final double k = 1.0 / math.sqrt(a);
+    u
+      ..x = 0.0
+      ..y = -planeNormal.z * k
+      ..z = planeNormal.y * k;
+
+    v
+      ..x = a * k
+      ..y = -planeNormal[0] * (planeNormal[1] * k)
+      ..z = planeNormal[0] * (-planeNormal[2] * k);
   } else {
     // choose u in x-y plane
-    double a = planeNormal.x * planeNormal.x + planeNormal.y * planeNormal.y;
-    double k = 1.0 / Math.sqrt(a);
-    u.x = -planeNormal[1] * k;
-    u.y = planeNormal[0] * k;
-    u.z = 0.0;
-    v.x = -planeNormal[2] * (planeNormal[0] * k);
-    v.y = planeNormal[2] * (-planeNormal[1] * k);
-    v.z = a * k;
+    final double a =
+        planeNormal.x * planeNormal.x + planeNormal.y * planeNormal.y;
+    final double k = 1.0 / math.sqrt(a);
+    u
+      ..x = -planeNormal[1] * k
+      ..y = planeNormal[0] * k
+      ..z = 0.0;
+
+    v
+      ..x = -planeNormal[2] * (planeNormal[0] * k)
+      ..y = planeNormal[2] * (-planeNormal[1] * k)
+      ..z = a * k;
   }
 }
 
diff --git a/pub/vector_math/lib/src/vector_math_64/vector2.dart b/pub/vector_math/lib/src/vector_math_64/vector2.dart
index 7e4e6e1..ef90099 100644
--- a/pub/vector_math/lib/src/vector_math_64/vector2.dart
+++ b/pub/vector_math/lib/src/vector_math_64/vector2.dart
@@ -9,25 +9,29 @@
   final Float64List _v2storage;
 
   /// The components of the vector.
+  @override
   Float64List get storage => _v2storage;
 
   /// Set the values of [result] to the minimum of [a] and [b] for each line.
   static void min(Vector2 a, Vector2 b, Vector2 result) {
-    result.x = Math.min(a.x, b.x);
-    result.y = Math.min(a.y, b.y);
+    result
+      ..x = math.min(a.x, b.x)
+      ..y = math.min(a.y, b.y);
   }
 
   /// Set the values of [result] to the maximum of [a] and [b] for each line.
   static void max(Vector2 a, Vector2 b, Vector2 result) {
-    result.x = Math.max(a.x, b.x);
-    result.y = Math.max(a.y, b.y);
+    result
+      ..x = math.max(a.x, b.x)
+      ..y = math.max(a.y, b.y);
   }
 
   /// Interpolate between [min] and [max] with the amount of [a] using a linear
   /// interpolation and store the values in [result].
   static void mix(Vector2 min, Vector2 max, double a, Vector2 result) {
-    result.x = min.x + a * (max.x - min.x);
-    result.y = min.y + a * (max.y - min.y);
+    result
+      ..x = min.x + a * (max.x - min.x)
+      ..y = min.y + a * (max.y - min.y);
   }
 
   /// Construct a new vector with the specified values.
@@ -56,8 +60,8 @@
 
   /// Generate random vector in the range (0, 0) to (1, 1). You can
   /// optionally pass your own random number generator.
-  factory Vector2.random([Math.Random rng]) {
-    rng = rng == null ? new Math.Random() : rng;
+  factory Vector2.random([math.Random rng]) {
+    rng = rng == null ? new math.Random() : rng;
     return new Vector2(rng.nextDouble(), rng.nextDouble());
   }
 
@@ -75,7 +79,7 @@
 
   /// Set the values by copying them from [other].
   void setFrom(Vector2 other) {
-    final otherStorage = other._v2storage;
+    final Float64List otherStorage = other._v2storage;
     _v2storage[1] = otherStorage[1];
     _v2storage[0] = otherStorage[0];
   }
@@ -87,15 +91,17 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[${_v2storage[0]},${_v2storage[1]}]';
 
   /// Check if two vectors are the same.
-  bool operator ==(other) {
-    return (other is Vector2) &&
-        (_v2storage[0] == other._v2storage[0]) &&
-        (_v2storage[1] == other._v2storage[1]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Vector2) &&
+      (_v2storage[0] == other._v2storage[0]) &&
+      (_v2storage[1] == other._v2storage[1]);
 
+  @override
   int get hashCode => quiver.hashObjects(_v2storage);
 
   /// Negate.
@@ -138,11 +144,11 @@
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Length squared.
   double get length2 {
-    var sum;
+    double sum;
     sum = (_v2storage[0] * _v2storage[0]);
     sum += (_v2storage[1] * _v2storage[1]);
     return sum;
@@ -150,11 +156,11 @@
 
   /// Normalize [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _v2storage[0] *= d;
     _v2storage[1] *= d;
     return l;
@@ -177,69 +183,67 @@
   }
 
   /// Distance from [this] to [arg]
-  double distanceTo(Vector2 arg) => Math.sqrt(distanceToSquared(arg));
+  double distanceTo(Vector2 arg) => math.sqrt(distanceToSquared(arg));
 
   /// Squared distance from [this] to [arg]
   double distanceToSquared(Vector2 arg) {
-    final dx = x - arg.x;
-    final dy = y - arg.y;
+    final double dx = x - arg.x;
+    final double dy = y - arg.y;
 
     return dx * dx + dy * dy;
   }
 
   /// Returns the angle between [this] vector and [other] in radians.
   double angleTo(Vector2 other) {
-    final otherStorage = other._v2storage;
-    if (_v2storage[0] == otherStorage[0] &&
-        _v2storage[1] == otherStorage[1]) {
+    final Float64List otherStorage = other._v2storage;
+    if (_v2storage[0] == otherStorage[0] && _v2storage[1] == otherStorage[1]) {
       return 0.0;
     }
 
-    final d = dot(other);
+    final double d = dot(other);
 
-    return Math.acos(d.clamp(-1.0, 1.0));
+    return math.acos(d.clamp(-1.0, 1.0));
   }
 
   /// Returns the signed angle between [this] and [other] in radians.
   double angleToSigned(Vector2 other) {
-    final otherStorage = other._v2storage;
-    if (_v2storage[0] == otherStorage[0] &&
-        _v2storage[1] == otherStorage[1]) {
+    final Float64List otherStorage = other._v2storage;
+    if (_v2storage[0] == otherStorage[0] && _v2storage[1] == otherStorage[1]) {
       return 0.0;
     }
 
-    final s = cross(other);
-    final c = dot(other);
+    final double s = cross(other);
+    final double c = dot(other);
 
-    return Math.atan2(s, c);
+    return math.atan2(s, c);
   }
 
   /// Inner product.
   double dot(Vector2 other) {
-    final otherStorage = other._v2storage;
+    final Float64List otherStorage = other._v2storage;
     double sum;
     sum = _v2storage[0] * otherStorage[0];
     sum += _v2storage[1] * otherStorage[1];
     return sum;
   }
 
-  /**
-   * Transforms [this] into the product of [this] as a row vector,
-   * postmultiplied by matrix, [arg].
-   * If [arg] is a rotation matrix, this is a computational shortcut for applying,
-   * the inverse of the transformation.
-   */
+  ///
+  /// Transforms [this] into the product of [this] as a row vector,
+  /// postmultiplied by matrix, [arg].
+  /// If [arg] is a rotation matrix, this is a computational shortcut for applying,
+  /// the inverse of the transformation.
+  ///
   void postmultiply(Matrix2 arg) {
-    final argStorage = arg.storage;
-    double v0 = _v2storage[0];
-    double v1 = _v2storage[1];
+    final Float64List argStorage = arg.storage;
+    final double v0 = _v2storage[0];
+    final double v1 = _v2storage[1];
     _v2storage[0] = v0 * argStorage[0] + v1 * argStorage[1];
     _v2storage[1] = v0 * argStorage[2] + v1 * argStorage[3];
   }
 
   /// Cross product.
   double cross(Vector2 other) {
-    final otherStorage = other._v2storage;
+    final Float64List otherStorage = other._v2storage;
     return _v2storage[0] * otherStorage[1] - _v2storage[1] * otherStorage[0];
   }
 
@@ -259,15 +263,13 @@
 
   /// Relative error between [this] and [correct]
   double relativeError(Vector2 correct) {
-    double correct_norm = correct.length;
-    double diff_norm = (this - correct).length;
+    final double correct_norm = correct.length;
+    final double diff_norm = (this - correct).length;
     return diff_norm / correct_norm;
   }
 
   /// Absolute error between [this] and [correct]
-  double absoluteError(Vector2 correct) {
-    return (this - correct).length;
-  }
+  double absoluteError(Vector2 correct) => (this - correct).length;
 
   /// True if any component is infinite.
   bool get isInfinite {
@@ -287,35 +289,35 @@
 
   /// Add [arg] to [this].
   void add(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] + argStorage[0];
     _v2storage[1] = _v2storage[1] + argStorage[1];
   }
 
   /// Add [arg] scaled by [factor] to [this].
   void addScaled(Vector2 arg, double factor) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] + argStorage[0] * factor;
     _v2storage[1] = _v2storage[1] + argStorage[1] * factor;
   }
 
   /// Subtract [arg] from [this].
   void sub(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] - argStorage[0];
     _v2storage[1] = _v2storage[1] - argStorage[1];
   }
 
   /// Multiply entries in [this] with entries in [arg].
   void multiply(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] * argStorage[0];
     _v2storage[1] = _v2storage[1] * argStorage[1];
   }
 
   /// Divide entries in [this] with entries in [arg].
   void divide(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v2storage[0] = _v2storage[0] / argStorage[0];
     _v2storage[1] = _v2storage[1] / argStorage[1];
   }
@@ -343,16 +345,18 @@
 
   /// Clamp each entry n in [this] in the range [min[n]]-[max[n]].
   void clamp(Vector2 min, Vector2 max) {
-    var minStorage = min.storage;
-    var maxStorage = max.storage;
-    _v2storage[0] = _v2storage[0].clamp(minStorage[0], maxStorage[0]);
-    _v2storage[1] = _v2storage[1].clamp(minStorage[1], maxStorage[1]);
+    final Float64List minStorage = min.storage;
+    final Float64List maxStorage = max.storage;
+    _v2storage[0] =
+        _v2storage[0].clamp(minStorage[0], maxStorage[0]).toDouble();
+    _v2storage[1] =
+        _v2storage[1].clamp(minStorage[1], maxStorage[1]).toDouble();
   }
 
   /// Clamp entries [this] in the range [min]-[max].
   void clampScalar(double min, double max) {
-    _v2storage[0] = _v2storage[0].clamp(min, max);
-    _v2storage[1] = _v2storage[1].clamp(min, max);
+    _v2storage[0] = _v2storage[0].clamp(min, max).toDouble();
+    _v2storage[1] = _v2storage[1].clamp(min, max).toDouble();
   }
 
   /// Floor entries in [this].
@@ -388,7 +392,7 @@
 
   /// Copy [this] into [arg]. Returns [arg].
   Vector2 copyInto(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     argStorage[1] = _v2storage[1];
     argStorage[0] = _v2storage[0];
     return arg;
@@ -407,13 +411,13 @@
   }
 
   set xy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v2storage[0] = argStorage[0];
     _v2storage[1] = argStorage[1];
   }
 
   set yx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v2storage[1] = argStorage[0];
     _v2storage[0] = argStorage[1];
   }
diff --git a/pub/vector_math/lib/src/vector_math_64/vector3.dart b/pub/vector_math/lib/src/vector_math_64/vector3.dart
index 40dc376..a356ed4 100644
--- a/pub/vector_math/lib/src/vector_math_64/vector3.dart
+++ b/pub/vector_math/lib/src/vector_math_64/vector3.dart
@@ -9,28 +9,32 @@
   final Float64List _v3storage;
 
   /// The components of the vector.
+  @override
   Float64List get storage => _v3storage;
 
   /// Set the values of [result] to the minimum of [a] and [b] for each line.
   static void min(Vector3 a, Vector3 b, Vector3 result) {
-    result.x = Math.min(a.x, b.x);
-    result.y = Math.min(a.y, b.y);
-    result.z = Math.min(a.z, b.z);
+    result
+      ..x = math.min(a.x, b.x)
+      ..y = math.min(a.y, b.y)
+      ..z = math.min(a.z, b.z);
   }
 
   /// Set the values of [result] to the maximum of [a] and [b] for each line.
   static void max(Vector3 a, Vector3 b, Vector3 result) {
-    result.x = Math.max(a.x, b.x);
-    result.y = Math.max(a.y, b.y);
-    result.z = Math.max(a.z, b.z);
+    result
+      ..x = math.max(a.x, b.x)
+      ..y = math.max(a.y, b.y)
+      ..z = math.max(a.z, b.z);
   }
 
   /// Interpolate between [min] and [max] with the amount of [a] using a linear
   /// interpolation and store the values in [result].
   static void mix(Vector3 min, Vector3 max, double a, Vector3 result) {
-    result.x = min.x + a * (max.x - min.x);
-    result.y = min.y + a * (max.y - min.y);
-    result.z = min.z + a * (max.z - min.z);
+    result
+      ..x = min.x + a * (max.x - min.x)
+      ..y = min.y + a * (max.y - min.y)
+      ..z = min.z + a * (max.z - min.z);
   }
 
   /// Construct a new vector with the specified values.
@@ -60,8 +64,8 @@
 
   /// Generate random vector in the range (0, 0, 0) to (1, 1, 1). You can
   /// optionally pass your own random number generator.
-  factory Vector3.random([Math.Random rng]) {
-    rng = rng == null ? new Math.Random() : rng;
+  factory Vector3.random([math.Random rng]) {
+    rng = rng == null ? new math.Random() : rng;
     return new Vector3(rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
   }
 
@@ -81,7 +85,7 @@
 
   /// Set the values by copying them from [other].
   void setFrom(Vector3 other) {
-    final otherStorage = other._v3storage;
+    final Float64List otherStorage = other._v3storage;
     _v3storage[0] = otherStorage[0];
     _v3storage[1] = otherStorage[1];
     _v3storage[2] = otherStorage[2];
@@ -95,16 +99,18 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '[${storage[0]},${storage[1]},${storage[2]}]';
 
   /// Check if two vectors are the same.
-  bool operator ==(other) {
-    return (other is Vector3) &&
-        (_v3storage[0] == other._v3storage[0]) &&
-        (_v3storage[1] == other._v3storage[1]) &&
-        (_v3storage[2] == other._v3storage[2]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Vector3) &&
+      (_v3storage[0] == other._v3storage[0]) &&
+      (_v3storage[1] == other._v3storage[1]) &&
+      (_v3storage[2] == other._v3storage[2]);
 
+  @override
   int get hashCode => quiver.hashObjects(_v3storage);
 
   /// Negate
@@ -148,7 +154,7 @@
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Length squared.
   double get length2 {
@@ -161,11 +167,11 @@
 
   /// Normalizes [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _v3storage[0] *= d;
     _v3storage[1] *= d;
     _v3storage[2] *= d;
@@ -189,45 +195,45 @@
   }
 
   /// Distance from [this] to [arg]
-  double distanceTo(Vector3 arg) => Math.sqrt(distanceToSquared(arg));
+  double distanceTo(Vector3 arg) => math.sqrt(distanceToSquared(arg));
 
   /// Squared distance from [this] to [arg]
   double distanceToSquared(Vector3 arg) {
-    final argStorage = arg._v3storage;
-    final dx = _v3storage[0] - argStorage[0];
-    final dy = _v3storage[1] - argStorage[1];
-    final dz = _v3storage[2] - argStorage[2];
+    final Float64List argStorage = arg._v3storage;
+    final double dx = _v3storage[0] - argStorage[0];
+    final double dy = _v3storage[1] - argStorage[1];
+    final double dz = _v3storage[2] - argStorage[2];
 
     return dx * dx + dy * dy + dz * dz;
   }
 
   /// Returns the angle between [this] vector and [other] in radians.
   double angleTo(Vector3 other) {
-    final otherStorage = other._v3storage;
+    final Float64List otherStorage = other._v3storage;
     if (_v3storage[0] == otherStorage[0] &&
         _v3storage[1] == otherStorage[1] &&
         _v3storage[2] == otherStorage[2]) {
       return 0.0;
     }
 
-    final d = dot(other);
+    final double d = dot(other);
 
-    return Math.acos(d.clamp(-1.0, 1.0));
+    return math.acos(d.clamp(-1.0, 1.0));
   }
 
   /// Returns the signed angle between [this] and [other] around [normal]
   /// in radians.
   double angleToSigned(Vector3 other, Vector3 normal) {
-    final angle = angleTo(other);
-    final c = cross(other);
-    final d = c.dot(normal);
+    final double angle = angleTo(other);
+    final Vector3 c = cross(other);
+    final double d = c.dot(normal);
 
     return d < 0.0 ? -angle : angle;
   }
 
   /// Inner product.
   double dot(Vector3 other) {
-    final otherStorage = other._v3storage;
+    final Float64List otherStorage = other._v3storage;
     double sum;
     sum = _v3storage[0] * otherStorage[0];
     sum += _v3storage[1] * otherStorage[1];
@@ -240,10 +246,10 @@
   /// If [arg] is a rotation matrix, this is a computational shortcut for applying,
   /// the inverse of the transformation.
   void postmultiply(Matrix3 arg) {
-    final argStorage = arg.storage;
-    final v0 = _v3storage[0];
-    final v1 = _v3storage[1];
-    final v2 = _v3storage[2];
+    final Float64List argStorage = arg.storage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
 
     _v3storage[0] =
         v0 * argStorage[0] + v1 * argStorage[1] + v2 * argStorage[2];
@@ -255,26 +261,26 @@
 
   /// Cross product.
   Vector3 cross(Vector3 other) {
-    final _x = _v3storage[0];
-    final _y = _v3storage[1];
-    final _z = _v3storage[2];
-    final otherStorage = other._v3storage;
-    final ox = otherStorage[0];
-    final oy = otherStorage[1];
-    final oz = otherStorage[2];
+    final double _x = _v3storage[0];
+    final double _y = _v3storage[1];
+    final double _z = _v3storage[2];
+    final Float64List otherStorage = other._v3storage;
+    final double ox = otherStorage[0];
+    final double oy = otherStorage[1];
+    final double oz = otherStorage[2];
     return new Vector3(_y * oz - _z * oy, _z * ox - _x * oz, _x * oy - _y * ox);
   }
 
   /// Cross product. Stores result in [out].
   Vector3 crossInto(Vector3 other, Vector3 out) {
-    final x = _v3storage[0];
-    final y = _v3storage[1];
-    final z = _v3storage[2];
-    final otherStorage = other._v3storage;
-    final ox = otherStorage[0];
-    final oy = otherStorage[1];
-    final oz = otherStorage[2];
-    final outStorage = out._v3storage;
+    final double x = _v3storage[0];
+    final double y = _v3storage[1];
+    final double z = _v3storage[2];
+    final Float64List otherStorage = other._v3storage;
+    final double ox = otherStorage[0];
+    final double oy = otherStorage[1];
+    final double oz = otherStorage[2];
+    final Float64List outStorage = out._v3storage;
     outStorage[0] = y * oz - z * oy;
     outStorage[1] = z * ox - x * oz;
     outStorage[2] = x * oy - y * ox;
@@ -291,11 +297,11 @@
 
   /// Projects [this] using the projection matrix [arg]
   void applyProjection(Matrix4 arg) {
-    final argStorage = arg.storage;
-    final x = _v3storage[0];
-    final y = _v3storage[1];
-    final z = _v3storage[2];
-    final d = 1.0 /
+    final Float64List argStorage = arg.storage;
+    final double x = _v3storage[0];
+    final double y = _v3storage[1];
+    final double z = _v3storage[2];
+    final double d = 1.0 /
         (argStorage[3] * x +
             argStorage[7] * y +
             argStorage[11] * z +
@@ -324,18 +330,18 @@
 
   /// Applies a quaternion transform.
   void applyQuaternion(Quaternion arg) {
-    final argStorage = arg._qStorage;
-    var v0 = _v3storage[0];
-    var v1 = _v3storage[1];
-    var v2 = _v3storage[2];
-    var qx = argStorage[0];
-    var qy = argStorage[1];
-    var qz = argStorage[2];
-    var qw = argStorage[3];
-    var ix = qw * v0 + qy * v2 - qz * v1;
-    var iy = qw * v1 + qz * v0 - qx * v2;
-    var iz = qw * v2 + qx * v1 - qy * v0;
-    var iw = -qx * v0 - qy * v1 - qz * v2;
+    final Float64List argStorage = arg._qStorage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
+    final double qx = argStorage[0];
+    final double qy = argStorage[1];
+    final double qz = argStorage[2];
+    final double qw = argStorage[3];
+    final double ix = qw * v0 + qy * v2 - qz * v1;
+    final double iy = qw * v1 + qz * v0 - qx * v2;
+    final double iz = qw * v2 + qx * v1 - qy * v0;
+    final double iw = -qx * v0 - qy * v1 - qz * v2;
     _v3storage[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
     _v3storage[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
     _v3storage[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
@@ -343,10 +349,10 @@
 
   /// Multiplies [this] by [arg].
   void applyMatrix3(Matrix3 arg) {
-    final argStorage = arg.storage;
-    var v0 = _v3storage[0];
-    var v1 = _v3storage[1];
-    var v2 = _v3storage[2];
+    final Float64List argStorage = arg.storage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
     _v3storage[0] =
         argStorage[0] * v0 + argStorage[3] * v1 + argStorage[6] * v2;
     _v3storage[1] =
@@ -358,10 +364,10 @@
   /// Multiplies [this] by a 4x3 subset of [arg]. Expects [arg] to be an affine
   /// transformation matrix.
   void applyMatrix4(Matrix4 arg) {
-    final argStorage = arg.storage;
-    var v0 = _v3storage[0];
-    var v1 = _v3storage[1];
-    var v2 = _v3storage[2];
+    final Float64List argStorage = arg.storage;
+    final double v0 = _v3storage[0];
+    final double v1 = _v3storage[1];
+    final double v2 = _v3storage[2];
     _v3storage[0] = argStorage[0] * v0 +
         argStorage[4] * v1 +
         argStorage[8] * v2 +
@@ -378,15 +384,13 @@
 
   /// Relative error between [this] and [correct]
   double relativeError(Vector3 correct) {
-    double correct_norm = correct.length;
-    double diff_norm = (this - correct).length;
+    final double correct_norm = correct.length;
+    final double diff_norm = (this - correct).length;
     return diff_norm / correct_norm;
   }
 
   /// Absolute error between [this] and [correct]
-  double absoluteError(Vector3 correct) {
-    return (this - correct).length;
-  }
+  double absoluteError(Vector3 correct) => (this - correct).length;
 
   /// True if any component is infinite.
   bool get isInfinite {
@@ -408,7 +412,7 @@
 
   /// Add [arg] to [this].
   void add(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] + argStorage[0];
     _v3storage[1] = _v3storage[1] + argStorage[1];
     _v3storage[2] = _v3storage[2] + argStorage[2];
@@ -416,7 +420,7 @@
 
   /// Add [arg] scaled by [factor] to [this].
   void addScaled(Vector3 arg, double factor) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] + argStorage[0] * factor;
     _v3storage[1] = _v3storage[1] + argStorage[1] * factor;
     _v3storage[2] = _v3storage[2] + argStorage[2] * factor;
@@ -424,7 +428,7 @@
 
   /// Subtract [arg] from [this].
   void sub(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] - argStorage[0];
     _v3storage[1] = _v3storage[1] - argStorage[1];
     _v3storage[2] = _v3storage[2] - argStorage[2];
@@ -432,7 +436,7 @@
 
   /// Multiply entries in [this] with entries in [arg].
   void multiply(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] * argStorage[0];
     _v3storage[1] = _v3storage[1] * argStorage[1];
     _v3storage[2] = _v3storage[2] * argStorage[2];
@@ -440,7 +444,7 @@
 
   /// Divide entries in [this] with entries in [arg].
   void divide(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[0] = _v3storage[0] / argStorage[0];
     _v3storage[1] = _v3storage[1] / argStorage[1];
     _v3storage[2] = _v3storage[2] / argStorage[2];
@@ -472,18 +476,21 @@
 
   /// Clamp each entry n in [this] in the range [min[n]]-[max[n]].
   void clamp(Vector3 min, Vector3 max) {
-    final minStorage = min.storage;
-    final maxStorage = max.storage;
-    _v3storage[0] = _v3storage[0].clamp(minStorage[0], maxStorage[0]);
-    _v3storage[1] = _v3storage[1].clamp(minStorage[1], maxStorage[1]);
-    _v3storage[2] = _v3storage[2].clamp(minStorage[2], maxStorage[2]);
+    final Float64List minStorage = min.storage;
+    final Float64List maxStorage = max.storage;
+    _v3storage[0] =
+        _v3storage[0].clamp(minStorage[0], maxStorage[0]).toDouble();
+    _v3storage[1] =
+        _v3storage[1].clamp(minStorage[1], maxStorage[1]).toDouble();
+    _v3storage[2] =
+        _v3storage[2].clamp(minStorage[2], maxStorage[2]).toDouble();
   }
 
   /// Clamp entries in [this] in the range [min]-[max].
   void clampScalar(double min, double max) {
-    _v3storage[0] = _v3storage[0].clamp(min, max);
-    _v3storage[1] = _v3storage[1].clamp(min, max);
-    _v3storage[2] = _v3storage[2].clamp(min, max);
+    _v3storage[0] = _v3storage[0].clamp(min, max).toDouble();
+    _v3storage[1] = _v3storage[1].clamp(min, max).toDouble();
+    _v3storage[2] = _v3storage[2].clamp(min, max).toDouble();
   }
 
   /// Floor entries in [this].
@@ -525,7 +532,7 @@
 
   /// Copy [this] into [arg].
   Vector3 copyInto(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     argStorage[0] = _v3storage[0];
     argStorage[1] = _v3storage[1];
     argStorage[2] = _v3storage[2];
@@ -547,78 +554,78 @@
   }
 
   set xy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v3storage[0] = argStorage[0];
     _v3storage[1] = argStorage[1];
   }
 
   set xz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v3storage[0] = argStorage[0];
     _v3storage[2] = argStorage[1];
   }
 
   set yx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v3storage[1] = argStorage[0];
     _v3storage[0] = argStorage[1];
   }
 
   set yz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v3storage[1] = argStorage[0];
     _v3storage[2] = argStorage[1];
   }
 
   set zx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v3storage[2] = argStorage[0];
     _v3storage[0] = argStorage[1];
   }
 
   set zy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v3storage[2] = argStorage[0];
     _v3storage[1] = argStorage[1];
   }
 
   set xyz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[0] = argStorage[0];
     _v3storage[1] = argStorage[1];
     _v3storage[2] = argStorage[2];
   }
 
   set xzy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[0] = argStorage[0];
     _v3storage[2] = argStorage[1];
     _v3storage[1] = argStorage[2];
   }
 
   set yxz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[1] = argStorage[0];
     _v3storage[0] = argStorage[1];
     _v3storage[2] = argStorage[2];
   }
 
   set yzx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[1] = argStorage[0];
     _v3storage[2] = argStorage[1];
     _v3storage[0] = argStorage[2];
   }
 
   set zxy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[2] = argStorage[0];
     _v3storage[0] = argStorage[1];
     _v3storage[1] = argStorage[2];
   }
 
   set zyx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v3storage[2] = argStorage[0];
     _v3storage[1] = argStorage[1];
     _v3storage[0] = argStorage[2];
diff --git a/pub/vector_math/lib/src/vector_math_64/vector4.dart b/pub/vector_math/lib/src/vector_math_64/vector4.dart
index e2d09df..5e27501 100644
--- a/pub/vector_math/lib/src/vector_math_64/vector4.dart
+++ b/pub/vector_math/lib/src/vector_math_64/vector4.dart
@@ -10,30 +10,34 @@
 
   /// Set the values of [result] to the minimum of [a] and [b] for each line.
   static void min(Vector4 a, Vector4 b, Vector4 result) {
-    result.x = Math.min(a.x, b.x);
-    result.y = Math.min(a.y, b.y);
-    result.z = Math.min(a.z, b.z);
-    result.w = Math.min(a.w, b.w);
+    result
+      ..x = math.min(a.x, b.x)
+      ..y = math.min(a.y, b.y)
+      ..z = math.min(a.z, b.z)
+      ..w = math.min(a.w, b.w);
   }
 
   /// Set the values of [result] to the maximum of [a] and [b] for each line.
   static void max(Vector4 a, Vector4 b, Vector4 result) {
-    result.x = Math.max(a.x, b.x);
-    result.y = Math.max(a.y, b.y);
-    result.z = Math.max(a.z, b.z);
-    result.w = Math.max(a.w, b.w);
+    result
+      ..x = math.max(a.x, b.x)
+      ..y = math.max(a.y, b.y)
+      ..z = math.max(a.z, b.z)
+      ..w = math.max(a.w, b.w);
   }
 
   /// Interpolate between [min] and [max] with the amount of [a] using a linear
   /// interpolation and store the values in [result].
   static void mix(Vector4 min, Vector4 max, double a, Vector4 result) {
-    result.x = min.x + a * (max.x - min.x);
-    result.y = min.y + a * (max.y - min.y);
-    result.z = min.z + a * (max.z - min.z);
-    result.w = min.w + a * (max.w - min.w);
+    result
+      ..x = min.x + a * (max.x - min.x)
+      ..y = min.y + a * (max.y - min.y)
+      ..z = min.z + a * (max.z - min.z)
+      ..w = min.w + a * (max.w - min.w);
   }
 
   /// The components of the vector.
+  @override
   Float64List get storage => _v4storage;
 
   /// Construct a new vector with the specified values.
@@ -66,10 +70,10 @@
 
   /// Generate random vector in the range (0, 0, 0, 0) to (1, 1, 1, 1). You can
   /// optionally pass your own random number generator.
-  factory Vector4.random([Math.Random rng]) {
-    rng = rng == null ? new Math.Random() : rng;
+  factory Vector4.random([math.Random rng]) {
+    rng = rng == null ? new math.Random() : rng;
     return new Vector4(
-      rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
+        rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
   }
 
   /// Set the values of the vector.
@@ -98,7 +102,7 @@
 
   /// Set the values by copying them from [other].
   void setFrom(Vector4 other) {
-    final otherStorage = other._v4storage;
+    final Float64List otherStorage = other._v4storage;
     _v4storage[3] = otherStorage[3];
     _v4storage[2] = otherStorage[2];
     _v4storage[1] = otherStorage[1];
@@ -114,18 +118,20 @@
   }
 
   /// Returns a printable string
+  @override
   String toString() => '${_v4storage[0]},${_v4storage[1]},'
       '${_v4storage[2]},${_v4storage[3]}';
 
   /// Check if two vectors are the same.
-  bool operator ==(other) {
-    return (other is Vector4) &&
-        (_v4storage[0] == other._v4storage[0]) &&
-        (_v4storage[1] == other._v4storage[1]) &&
-        (_v4storage[2] == other._v4storage[2]) &&
-        (_v4storage[3] == other._v4storage[3]);
-  }
+  @override
+  bool operator ==(Object other) =>
+      (other is Vector4) &&
+      (_v4storage[0] == other._v4storage[0]) &&
+      (_v4storage[1] == other._v4storage[1]) &&
+      (_v4storage[2] == other._v4storage[2]) &&
+      (_v4storage[3] == other._v4storage[3]);
 
+  @override
   int get hashCode => quiver.hashObjects(_v4storage);
 
   /// Negate.
@@ -170,7 +176,7 @@
   }
 
   /// Length.
-  double get length => Math.sqrt(length2);
+  double get length => math.sqrt(length2);
 
   /// Length squared.
   double get length2 {
@@ -184,11 +190,11 @@
 
   /// Normalizes [this].
   double normalize() {
-    double l = length;
+    final double l = length;
     if (l == 0.0) {
       return 0.0;
     }
-    var d = 1.0 / l;
+    final double d = 1.0 / l;
     _v4storage[0] *= d;
     _v4storage[1] *= d;
     _v4storage[2] *= d;
@@ -213,22 +219,22 @@
   }
 
   /// Distance from [this] to [arg]
-  double distanceTo(Vector4 arg) => Math.sqrt(distanceToSquared(arg));
+  double distanceTo(Vector4 arg) => math.sqrt(distanceToSquared(arg));
 
   /// Squared distance from [this] to [arg]
   double distanceToSquared(Vector4 arg) {
-    final argStorage = arg._v4storage;
-    final dx = _v4storage[0] - argStorage[0];
-    final dy = _v4storage[1] - argStorage[1];
-    final dz = _v4storage[2] - argStorage[2];
-    final dw = _v4storage[3] - argStorage[3];
+    final Float64List argStorage = arg._v4storage;
+    final double dx = _v4storage[0] - argStorage[0];
+    final double dy = _v4storage[1] - argStorage[1];
+    final double dz = _v4storage[2] - argStorage[2];
+    final double dw = _v4storage[3] - argStorage[3];
 
     return dx * dx + dy * dy + dz * dz + dw * dw;
   }
 
   /// Inner product.
   double dot(Vector4 other) {
-    final otherStorage = other._v4storage;
+    final Float64List otherStorage = other._v4storage;
     double sum;
     sum = _v4storage[0] * otherStorage[0];
     sum += _v4storage[1] * otherStorage[1];
@@ -239,11 +245,11 @@
 
   /// Multiplies [this] by [arg].
   void applyMatrix4(Matrix4 arg) {
-    var v1 = _v4storage[0];
-    var v2 = _v4storage[1];
-    var v3 = _v4storage[2];
-    var v4 = _v4storage[3];
-    final argStorage = arg.storage;
+    final double v1 = _v4storage[0];
+    final double v2 = _v4storage[1];
+    final double v3 = _v4storage[2];
+    final double v4 = _v4storage[3];
+    final Float64List argStorage = arg.storage;
     _v4storage[0] = argStorage[0] * v1 +
         argStorage[4] * v2 +
         argStorage[8] * v3 +
@@ -264,15 +270,13 @@
 
   /// Relative error between [this] and [correct]
   double relativeError(Vector4 correct) {
-    double correct_norm = correct.length;
-    double diff_norm = (this - correct).length;
+    final double correct_norm = correct.length;
+    final double diff_norm = (this - correct).length;
     return diff_norm / correct_norm;
   }
 
   /// Absolute error between [this] and [correct]
-  double absoluteError(Vector4 correct) {
-    return (this - correct).length;
-  }
+  double absoluteError(Vector4 correct) => (this - correct).length;
 
   /// True if any component is infinite.
   bool get isInfinite {
@@ -295,7 +299,7 @@
   }
 
   void add(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] + argStorage[0];
     _v4storage[1] = _v4storage[1] + argStorage[1];
     _v4storage[2] = _v4storage[2] + argStorage[2];
@@ -304,7 +308,7 @@
 
   /// Add [arg] scaled by [factor] to [this].
   void addScaled(Vector4 arg, double factor) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] + argStorage[0] * factor;
     _v4storage[1] = _v4storage[1] + argStorage[1] * factor;
     _v4storage[2] = _v4storage[2] + argStorage[2] * factor;
@@ -313,7 +317,7 @@
 
   /// Subtract [arg] from [this].
   void sub(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] - argStorage[0];
     _v4storage[1] = _v4storage[1] - argStorage[1];
     _v4storage[2] = _v4storage[2] - argStorage[2];
@@ -322,7 +326,7 @@
 
   /// Multiply [this] by [arg].
   void multiply(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] * argStorage[0];
     _v4storage[1] = _v4storage[1] * argStorage[1];
     _v4storage[2] = _v4storage[2] * argStorage[2];
@@ -331,7 +335,7 @@
 
   /// Divide [this] by [arg].
   void div(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = _v4storage[0] / argStorage[0];
     _v4storage[1] = _v4storage[1] / argStorage[1];
     _v4storage[2] = _v4storage[2] / argStorage[2];
@@ -367,20 +371,24 @@
 
   /// Clamp each entry n in [this] in the range [min[n]]-[max[n]].
   void clamp(Vector4 min, Vector4 max) {
-    final minStorage = min.storage;
-    final maxStorage = max.storage;
-    _v4storage[0] = _v4storage[0].clamp(minStorage[0], maxStorage[0]);
-    _v4storage[1] = _v4storage[1].clamp(minStorage[1], maxStorage[1]);
-    _v4storage[2] = _v4storage[2].clamp(minStorage[2], maxStorage[2]);
-    _v4storage[3] = _v4storage[3].clamp(minStorage[3], maxStorage[3]);
+    final Float64List minStorage = min.storage;
+    final Float64List maxStorage = max.storage;
+    _v4storage[0] =
+        _v4storage[0].clamp(minStorage[0], maxStorage[0]).toDouble();
+    _v4storage[1] =
+        _v4storage[1].clamp(minStorage[1], maxStorage[1]).toDouble();
+    _v4storage[2] =
+        _v4storage[2].clamp(minStorage[2], maxStorage[2]).toDouble();
+    _v4storage[3] =
+        _v4storage[3].clamp(minStorage[3], maxStorage[3]).toDouble();
   }
 
   /// Clamp entries in [this] in the range [min]-[max].
   void clampScalar(double min, double max) {
-    _v4storage[0] = _v4storage[0].clamp(min, max);
-    _v4storage[1] = _v4storage[1].clamp(min, max);
-    _v4storage[2] = _v4storage[2].clamp(min, max);
-    _v4storage[3] = _v4storage[3].clamp(min, max);
+    _v4storage[0] = _v4storage[0].clamp(min, max).toDouble();
+    _v4storage[1] = _v4storage[1].clamp(min, max).toDouble();
+    _v4storage[2] = _v4storage[2].clamp(min, max).toDouble();
+    _v4storage[3] = _v4storage[3].clamp(min, max).toDouble();
   }
 
   /// Floor entries in [this].
@@ -428,7 +436,7 @@
 
   /// Copy [this]
   Vector4 copyInto(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     argStorage[0] = _v4storage[0];
     argStorage[1] = _v4storage[1];
     argStorage[2] = _v4storage[2];
@@ -453,247 +461,247 @@
   }
 
   set xy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
   }
 
   set xz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
   }
 
   set xw(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
   }
 
   set yx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
   }
 
   set yz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
   }
 
   set yw(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
   }
 
   set zx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
   }
 
   set zy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
   }
 
   set zw(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
   }
 
   set wx(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
   }
 
   set wy(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
   }
 
   set wz(Vector2 arg) {
-    final argStorage = arg._v2storage;
+    final Float64List argStorage = arg._v2storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
   }
 
   set xyz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set xyw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set xzy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set xzw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set xwy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set xwz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set yxz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set yxw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set yzx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set yzw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set ywx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set ywz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set zxy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set zxw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set zyx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set zyw(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
   }
 
   set zwx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set zwy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set wxy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set wxz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set wyx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set wyz(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
   }
 
   set wzx(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
   }
 
   set wzy(Vector3 arg) {
-    final argStorage = arg._v3storage;
+    final Float64List argStorage = arg._v3storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
   }
 
   set xyzw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -701,7 +709,7 @@
   }
 
   set xywz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -709,7 +717,7 @@
   }
 
   set xzyw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -717,7 +725,7 @@
   }
 
   set xzwy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -725,7 +733,7 @@
   }
 
   set xwyz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -733,7 +741,7 @@
   }
 
   set xwzy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[0] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -741,7 +749,7 @@
   }
 
   set yxzw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -749,7 +757,7 @@
   }
 
   set yxwz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -757,7 +765,7 @@
   }
 
   set yzxw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -765,7 +773,7 @@
   }
 
   set yzwx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -773,7 +781,7 @@
   }
 
   set ywxz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -781,7 +789,7 @@
   }
 
   set ywzx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[1] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -789,7 +797,7 @@
   }
 
   set zxyw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -797,7 +805,7 @@
   }
 
   set zxwy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -805,7 +813,7 @@
   }
 
   set zyxw(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -813,7 +821,7 @@
   }
 
   set zywx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[3] = argStorage[2];
@@ -821,7 +829,7 @@
   }
 
   set zwxy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -829,7 +837,7 @@
   }
 
   set zwyx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[2] = argStorage[0];
     _v4storage[3] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -837,7 +845,7 @@
   }
 
   set wxyz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[1] = argStorage[2];
@@ -845,7 +853,7 @@
   }
 
   set wxzy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[0] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -853,7 +861,7 @@
   }
 
   set wyxz(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -861,7 +869,7 @@
   }
 
   set wyzx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[1] = argStorage[1];
     _v4storage[2] = argStorage[2];
@@ -869,7 +877,7 @@
   }
 
   set wzxy(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[0] = argStorage[2];
@@ -877,7 +885,7 @@
   }
 
   set wzyx(Vector4 arg) {
-    final argStorage = arg._v4storage;
+    final Float64List argStorage = arg._v4storage;
     _v4storage[3] = argStorage[0];
     _v4storage[2] = argStorage[1];
     _v4storage[1] = argStorage[2];
diff --git a/pub/vector_math/lib/src/vector_math_geometry/filters/barycentric_filter.dart b/pub/vector_math/lib/src/vector_math_geometry/filters/barycentric_filter.dart
index 81a9a61..afd26ed 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/filters/barycentric_filter.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/filters/barycentric_filter.dart
@@ -5,23 +5,32 @@
 part of vector_math_geometry;
 
 class BarycentricFilter extends GeometryFilter {
+  @override
   List<VertexAttrib> get generates =>
-      [new VertexAttrib('BARYCENTRIC', 3, 'float')];
+      <VertexAttrib>[new VertexAttrib('BARYCENTRIC', 3, 'float')];
 
+  @override
   MeshGeometry filter(MeshGeometry mesh) {
-    List<VertexAttrib> newAttribs =
+    final List<VertexAttrib> newAttribs =
         new List<VertexAttrib>.from(mesh.attribs, growable: true);
 
     if (mesh.getAttrib('BARYCENTRIC') == null) {
       newAttribs.add(new VertexAttrib('BARYCENTRIC', 3, 'float'));
     }
 
-    MeshGeometry output =
+    final MeshGeometry output =
         new MeshGeometry(mesh.triangleVertexCount, newAttribs);
-    Vector3List barycentricCoords = output.getViewForAttrib('BARYCENTRIC');
 
-    List<VectorList> srcAttribs = new List<VectorList>();
-    List<VectorList> destAttribs = new List<VectorList>();
+    Vector3List barycentricCoords;
+    final VectorList<Vector> view = output.getViewForAttrib('BARYCENTRIC');
+    if (view is Vector3List) {
+      barycentricCoords = view;
+    } else {
+      return null;
+    }
+
+    final List<VectorList<Vector>> srcAttribs = <VectorList<Vector>>[];
+    final List<VectorList<Vector>> destAttribs = <VectorList<Vector>>[];
     for (VertexAttrib attrib in mesh.attribs) {
       if (attrib.name == 'BARYCENTRIC') {
         continue;
@@ -31,9 +40,9 @@
       destAttribs.add(output.getViewForAttrib(attrib.name));
     }
 
-    Vector3 b0 = new Vector3(1.0, 0.0, 0.0);
-    Vector3 b1 = new Vector3(0.0, 1.0, 0.0);
-    Vector3 b2 = new Vector3(0.0, 0.0, 1.0);
+    final Vector3 b0 = new Vector3(1.0, 0.0, 0.0);
+    final Vector3 b1 = new Vector3(0.0, 1.0, 0.0);
+    final Vector3 b2 = new Vector3(0.0, 0.0, 1.0);
 
     int i0, i1, i2;
 
diff --git a/pub/vector_math/lib/src/vector_math_geometry/filters/color_filter.dart b/pub/vector_math/lib/src/vector_math_geometry/filters/color_filter.dart
index 8cd5902..4ac043a 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/filters/color_filter.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/filters/color_filter.dart
@@ -7,26 +7,32 @@
 class ColorFilter extends GeometryFilter {
   Vector4 color;
 
-  List<VertexAttrib> get generates => [new VertexAttrib('COLOR', 4, 'float')];
+  ColorFilter(this.color);
 
-  ColorFilter(Vector4 this.color);
+  @override
+  List<VertexAttrib> get generates =>
+      <VertexAttrib>[new VertexAttrib('COLOR', 4, 'float')];
 
+  @override
   MeshGeometry filter(MeshGeometry mesh) {
     MeshGeometry output;
     if (mesh.getAttrib('COLOR') == null) {
-      List<VertexAttrib> attributes = new List<VertexAttrib>();
-      attributes.addAll(mesh.attribs);
-      attributes.add(new VertexAttrib('COLOR', 4, 'float'));
+      final List<VertexAttrib> attributes = <VertexAttrib>[]
+        ..addAll(mesh.attribs)
+        ..add(new VertexAttrib('COLOR', 4, 'float'));
       output = new MeshGeometry.resetAttribs(mesh, attributes);
     } else {
       output = new MeshGeometry.copy(mesh);
     }
 
-    Vector4List colors = output.getViewForAttrib('COLOR');
-    for (int i = 0; i < colors.length; ++i) {
-      colors[i] = color;
+    final VectorList<Vector> colors = output.getViewForAttrib('COLOR');
+    if (colors is Vector4List) {
+      for (int i = 0; i < colors.length; ++i) {
+        colors[i] = color;
+      }
+      return output;
+    } else {
+      return null;
     }
-
-    return output;
   }
 }
diff --git a/pub/vector_math/lib/src/vector_math_geometry/filters/flat_shade_filter.dart b/pub/vector_math/lib/src/vector_math_geometry/filters/flat_shade_filter.dart
index 6da8eb1..41b8d87 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/filters/flat_shade_filter.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/filters/flat_shade_filter.dart
@@ -5,30 +5,42 @@
 part of vector_math_geometry;
 
 class FlatShadeFilter extends GeometryFilter {
-  List<VertexAttrib> get requires => [new VertexAttrib('POSITION', 3, 'float')];
-  List<VertexAttrib> get generates => [new VertexAttrib('NORMAL', 3, 'float')];
+  @override
+  List<VertexAttrib> get requires =>
+      <VertexAttrib>[new VertexAttrib('POSITION', 3, 'float')];
 
+  @override
+  List<VertexAttrib> get generates =>
+      <VertexAttrib>[new VertexAttrib('NORMAL', 3, 'float')];
+
+  @override
   MeshGeometry filter(MeshGeometry mesh) {
-    List<VertexAttrib> newAttribs =
+    final List<VertexAttrib> newAttribs =
         new List<VertexAttrib>.from(mesh.attribs, growable: true);
 
     if (mesh.getAttrib('NORMAL') == null) {
       newAttribs.add(new VertexAttrib('NORMAL', 3, 'float'));
     }
 
-    MeshGeometry output =
+    final MeshGeometry output =
         new MeshGeometry(mesh.triangleVertexCount, newAttribs);
 
-    Vector3 p0 = new Vector3.zero(),
+    final Vector3 p0 = new Vector3.zero(),
         p1 = new Vector3.zero(),
         p2 = new Vector3.zero();
 
-    Vector3List srcPosition = mesh.getViewForAttrib('POSITION');
-    Vector3List destPosition = output.getViewForAttrib('POSITION');
-    Vector3List normals = output.getViewForAttrib('NORMAL');
+    final VectorList<Vector> srcPosition = mesh.getViewForAttrib('POSITION');
+    final VectorList<Vector> destPosition = output.getViewForAttrib('POSITION');
+    final VectorList<Vector> normals = output.getViewForAttrib('NORMAL');
 
-    List<VectorList> srcAttribs = new List<VectorList>();
-    List<VectorList> destAttribs = new List<VectorList>();
+    if (srcPosition is! Vector3List ||
+        destPosition is! Vector3List ||
+        normals is! Vector3List) {
+      return null;
+    }
+
+    final List<VectorList<Vector>> srcAttribs = <VectorList<Vector>>[];
+    final List<VectorList<Vector>> destAttribs = <VectorList<Vector>>[];
     for (VertexAttrib attrib in mesh.attribs) {
       if (attrib.name == 'POSITION' || attrib.name == 'NORMAL') {
         continue;
@@ -39,13 +51,11 @@
     }
 
     for (int i = 0; i < output.length; i += 3) {
-      int i0 = mesh.indices[i];
-      int i1 = mesh.indices[i + 1];
-      int i2 = mesh.indices[i + 2];
+      final int i0 = mesh.indices[i];
+      final int i1 = mesh.indices[i + 1];
+      final int i2 = mesh.indices[i + 2];
 
-      srcPosition.load(i0, p0);
-      srcPosition.load(i1, p1);
-      srcPosition.load(i2, p2);
+      srcPosition..load(i0, p0)..load(i1, p1)..load(i2, p2);
 
       destPosition[i] = p0;
       destPosition[i + 1] = p1;
diff --git a/pub/vector_math/lib/src/vector_math_geometry/filters/geometry_filter.dart b/pub/vector_math/lib/src/vector_math_geometry/filters/geometry_filter.dart
index 78068b5..f678719 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/filters/geometry_filter.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/filters/geometry_filter.dart
@@ -6,17 +6,20 @@
 
 abstract class GeometryFilter {
   bool get inplace => false;
-  List<VertexAttrib> get requires => [];
-  List<VertexAttrib> get generates => [];
+  List<VertexAttrib> get requires => <VertexAttrib>[];
+  List<VertexAttrib> get generates => <VertexAttrib>[];
 
   /// Returns a copy of the mesh with any filter transforms applied.
   MeshGeometry filter(MeshGeometry mesh);
 }
 
 abstract class InplaceGeometryFilter extends GeometryFilter {
+  @override
   bool get inplace => true;
+
+  @override
   MeshGeometry filter(MeshGeometry mesh) {
-    MeshGeometry output = new MeshGeometry.copy(mesh);
+    final MeshGeometry output = new MeshGeometry.copy(mesh);
     filterInplace(output);
     return output;
   }
diff --git a/pub/vector_math/lib/src/vector_math_geometry/filters/invert_filter.dart b/pub/vector_math/lib/src/vector_math_geometry/filters/invert_filter.dart
index 0a2a4a1..8d2e6bc 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/filters/invert_filter.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/filters/invert_filter.dart
@@ -5,6 +5,7 @@
 part of vector_math_geometry;
 
 class InvertFilter extends InplaceGeometryFilter {
+  @override
   void filterInplace(MeshGeometry mesh) {
     // TODO: Do the tangents need to be inverted? Maybe just the W component?
     // TODO: Should modify in-place be allowed, or should it be required
@@ -12,13 +13,13 @@
 
     // Swap all the triangle indices
     for (int i = 0; i < mesh.indices.length; i += 3) {
-      int tmp = mesh.indices[i];
+      final int tmp = mesh.indices[i];
       mesh.indices[i] = mesh.indices[i + 2];
       mesh.indices[i + 2] = tmp;
     }
 
-    Vector3List normals = mesh.getViewForAttrib('NORMAL');
-    if (normals != null) {
+    final VectorList<Vector> normals = mesh.getViewForAttrib('NORMAL');
+    if (normals is Vector3List) {
       for (int i = 0; i < normals.length; ++i) {
         normals[i] = -normals[i];
       }
diff --git a/pub/vector_math/lib/src/vector_math_geometry/filters/transform_filter.dart b/pub/vector_math/lib/src/vector_math_geometry/filters/transform_filter.dart
index a09b174..bb3db62 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/filters/transform_filter.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/filters/transform_filter.dart
@@ -6,14 +6,20 @@
 
 class TransformFilter extends InplaceGeometryFilter {
   Matrix4 transform;
-  List<VertexAttrib> get requires => [new VertexAttrib('POSITION', 3, 'float')];
 
-  TransformFilter(Matrix4 this.transform);
+  TransformFilter(this.transform);
 
+  @override
+  List<VertexAttrib> get requires =>
+      <VertexAttrib>[new VertexAttrib('POSITION', 3, 'float')];
+
+  @override
   void filterInplace(MeshGeometry mesh) {
-    Vector3List position = mesh.getViewForAttrib('POSITION');
-    if (position != null) {
+    final VectorList<Vector> position = mesh.getViewForAttrib('POSITION');
+    if (position is Vector3List) {
       for (int i = 0; i < position.length; ++i) {
+        // multiplication always returns Vector3 here
+        // ignore: invalid_assignment
         position[i] = transform * position[i];
       }
     }
diff --git a/pub/vector_math/lib/src/vector_math_geometry/generators/attribute_generators.dart b/pub/vector_math/lib/src/vector_math_geometry/generators/attribute_generators.dart
index c53c86f..415942c 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/generators/attribute_generators.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/generators/attribute_generators.dart
@@ -9,7 +9,7 @@
 /// [indices] is assumed to represent a triangle list.
 void generateNormals(
     Vector3List normals, Vector3List positions, Uint16List indices) {
-  Vector3 p0 = new Vector3.zero(),
+  final Vector3 p0 = new Vector3.zero(),
       p1 = new Vector3.zero(),
       p2 = new Vector3.zero(),
       norm = new Vector3.zero();
@@ -17,10 +17,8 @@
   // Loop through every polygon, find it's normal, and add that to the vertex
   // normals.
   for (int i = 0; i < indices.length; i += 3) {
-    int i0 = indices[i], i1 = indices[i + 1], i2 = indices[i + 2];
-    positions.load(i0, p0);
-    positions.load(i1, p1);
-    positions.load(i2, p2);
+    final int i0 = indices[i], i1 = indices[i + 1], i2 = indices[i + 2];
+    positions..load(i0, p0)..load(i1, p1)..load(i2, p2);
 
     p1.sub(p0);
     p2.sub(p0);
@@ -59,7 +57,7 @@
 /// http://www.terathon.com/code/tangent.html
 void generateTangents(Vector4List tangents, Vector3List positions,
     Vector3List normals, Vector2List texCoords, Uint16List indices) {
-  Vector3 p0 = new Vector3.zero(),
+  final Vector3 p0 = new Vector3.zero(),
       p1 = new Vector3.zero(),
       p2 = new Vector3.zero(),
       n = new Vector3.zero(),
@@ -67,24 +65,20 @@
       udir = new Vector3.zero(),
       vdir = new Vector3.zero();
 
-  Vector2 uv0 = new Vector2.zero(),
+  final Vector2 uv0 = new Vector2.zero(),
       uv1 = new Vector2.zero(),
       uv2 = new Vector2.zero();
 
-  Vector4 tan = new Vector4.zero();
+  final Vector4 tan = new Vector4.zero();
 
-  Vector3List tan0 = new Vector3List(positions.length),
+  final Vector3List tan0 = new Vector3List(positions.length),
       tan1 = new Vector3List(positions.length);
 
   for (int i = 0; i < indices.length; i += 3) {
-    int i0 = indices[i], i1 = indices[i + 1], i2 = indices[i + 2];
-    positions.load(i0, p0);
-    positions.load(i1, p1);
-    positions.load(i2, p2);
+    final int i0 = indices[i], i1 = indices[i + 1], i2 = indices[i + 2];
+    positions..load(i0, p0)..load(i1, p1)..load(i2, p2);
 
-    texCoords.load(i0, uv0);
-    texCoords.load(i1, uv1);
-    texCoords.load(i2, uv2);
+    texCoords..load(i0, uv0)..load(i1, uv1)..load(i2, uv2);
 
     p1.sub(p0);
     p2.sub(p0);
@@ -92,7 +86,7 @@
     uv1.sub(uv0);
     uv2.sub(uv0);
 
-    double r = 1.0 / (uv1.x * uv2.y - uv2.x * uv1.y);
+    final double r = 1.0 / (uv1.x * uv2.y - uv2.x * uv1.y);
 
     udir.setValues((uv2.y * p1.x - uv1.y * p2.x) * r,
         (uv2.y * p1.y - uv1.y * p2.y) * r, (uv2.y * p1.z - uv1.y * p2.z) * r);
@@ -128,7 +122,7 @@
 
     tan1.load(i, p1);
     n.crossInto(t, p2);
-    double sign = (p2.dot(p1) < 0.0) ? -1.0 : 1.0;
+    final double sign = (p2.dot(p1) < 0.0) ? -1.0 : 1.0;
 
     tangents.load(i, tan);
     tangents[i] = tan..setValues(p0.x, p0.y, p0.z, sign);
diff --git a/pub/vector_math/lib/src/vector_math_geometry/generators/circle_generator.dart b/pub/vector_math/lib/src/vector_math_geometry/generators/circle_generator.dart
index 9803f2c..d49a01c 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/generators/circle_generator.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/generators/circle_generator.dart
@@ -10,15 +10,18 @@
   double _thetaStart;
   double _thetaLength;
 
+  @override
   int get vertexCount => _segments + 2;
+
+  @override
   int get indexCount => (_segments) * 3;
 
   MeshGeometry createCircle(double radius,
-      {flags: null,
-      filters: null,
-      segments: 64,
-      thetaStart: 0.0,
-      thetaLength: Math.PI * 2.0}) {
+      {GeometryGeneratorFlags flags: null,
+      List<GeometryFilter> filters: null,
+      int segments: 64,
+      double thetaStart: 0.0,
+      double thetaLength: math.PI * 2.0}) {
     _radius = radius;
     _segments = segments;
     _thetaStart = thetaStart;
@@ -26,37 +29,42 @@
     return createGeometry(flags: flags, filters: filters);
   }
 
+  @override
   void generateVertexPositions(Vector3List positions, Uint16List indices) {
-    Vector3 v = new Vector3.zero();
+    final Vector3 v = new Vector3.zero();
     positions[0] = v;
     int index = 1;
     for (int i = 0; i <= _segments; i++) {
-      double percent = i / _segments;
-      v.x = _radius * Math.cos(_thetaStart + percent * _thetaLength);
-      v.z = _radius * Math.sin(_thetaStart + percent * _thetaLength);
+      final double percent = i / _segments;
+      v
+        ..x = _radius * math.cos(_thetaStart + percent * _thetaLength)
+        ..z = _radius * math.sin(_thetaStart + percent * _thetaLength);
       positions[index] = v;
       index++;
     }
     assert(index == vertexCount);
   }
 
+  @override
   void generateVertexTexCoords(
       Vector2List texCoords, Vector3List positions, Uint16List indices) {
-    Vector2 v = new Vector2(0.5, 0.5);
+    final Vector2 v = new Vector2(0.5, 0.5);
     texCoords[0] = v;
     int index = 1;
     for (int i = 0; i <= _segments; i++) {
-      Vector3 position = positions[index];
-      double x = (position.x / (_radius + 1.0)) * 0.5;
-      double y = (position.z / (_radius + 1.0)) * 0.5;
-      v.x = x + 0.5;
-      v.y = y + 0.5;
+      final Vector3 position = positions[index];
+      final double x = (position.x / (_radius + 1.0)) * 0.5;
+      final double y = (position.z / (_radius + 1.0)) * 0.5;
+      v
+        ..x = x + 0.5
+        ..y = y + 0.5;
       texCoords[index] = v;
       index++;
     }
     assert(index == vertexCount);
   }
 
+  @override
   void generateIndices(Uint16List indices) {
     int index = 0;
     for (int i = 1; i <= _segments; i++) {
diff --git a/pub/vector_math/lib/src/vector_math_geometry/generators/cube_generator.dart b/pub/vector_math/lib/src/vector_math_geometry/generators/cube_generator.dart
index 3d379a9..b0948a7 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/generators/cube_generator.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/generators/cube_generator.dart
@@ -9,11 +9,15 @@
   double _height;
   double _depth;
 
+  @override
   int get vertexCount => 24;
+
+  @override
   int get indexCount => 36;
 
   MeshGeometry createCube(num width, num height, num depth,
-      {flags: null, filters: null}) {
+      {GeometryGeneratorFlags flags: null,
+      List<GeometryFilter> filters: null}) {
     _width = width.toDouble();
     _height = height.toDouble();
     _depth = depth.toDouble();
@@ -21,8 +25,9 @@
     return createGeometry(flags: flags, filters: filters);
   }
 
+  @override
   void generateIndices(Uint16List indices) {
-    indices.setAll(0, [
+    indices.setAll(0, <int>[
       0,
       1,
       2,
@@ -62,6 +67,7 @@
     ]);
   }
 
+  @override
   void generateVertexPositions(Vector3List positions, Uint16List indices) {
     // Front
     positions[0] = new Vector3(_width, _height, _depth);
@@ -100,6 +106,7 @@
     positions[23] = new Vector3(_width, -_height, _depth);
   }
 
+  @override
   void generateVertexTexCoords(
       Vector2List texCoords, Vector3List positions, Uint16List indices) {
     // Front
diff --git a/pub/vector_math/lib/src/vector_math_geometry/generators/cylinder_generator.dart b/pub/vector_math/lib/src/vector_math_geometry/generators/cylinder_generator.dart
index dc40992..1cb4045 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/generators/cylinder_generator.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/generators/cylinder_generator.dart
@@ -10,11 +10,16 @@
   double _height;
   int _segments;
 
+  @override
   int get vertexCount => ((_segments + 1) * 2) + (_segments * 2);
+
+  @override
   int get indexCount => (_segments * 6) + ((_segments - 2) * 6);
 
   MeshGeometry createCylinder(num topRadius, num bottomRadius, num height,
-      {int segments: 16, flags: null, filters: null}) {
+      {int segments: 16,
+      GeometryGeneratorFlags flags: null,
+      List<GeometryFilter> filters: null}) {
     _topRadius = topRadius.toDouble();
     _bottomRadius = bottomRadius.toDouble();
     _height = height.toDouble();
@@ -23,12 +28,13 @@
     return createGeometry(flags: flags, filters: filters);
   }
 
+  @override
   void generateIndices(Uint16List indices) {
     int i = 0;
 
     // Sides
     int base1 = 0;
-    int base2 = _segments + 1;
+    final int base2 = _segments + 1;
     for (int x = 0; x < _segments; ++x) {
       indices[i++] = base1 + x;
       indices[i++] = base1 + x + 1;
@@ -56,70 +62,72 @@
     }
   }
 
+  @override
   void generateVertexPositions(Vector3List positions, Uint16List indices) {
     int i = 0;
 
     // Top
     for (int x = 0; x <= _segments; ++x) {
-      double u = x / _segments;
+      final double u = x / _segments;
 
-      positions[i++] = new Vector3(_topRadius * Math.cos(u * Math.PI * 2.0),
-          _height * 0.5, _topRadius * Math.sin(u * Math.PI * 2.0));
+      positions[i++] = new Vector3(_topRadius * math.cos(u * math.PI * 2.0),
+          _height * 0.5, _topRadius * math.sin(u * math.PI * 2.0));
     }
 
     // Bottom
     for (int x = 0; x <= _segments; ++x) {
-      double u = x / _segments;
+      final double u = x / _segments;
 
-      positions[i++] = new Vector3(_bottomRadius * Math.cos(u * Math.PI * 2.0),
-          _height * -0.5, _bottomRadius * Math.sin(u * Math.PI * 2.0));
+      positions[i++] = new Vector3(_bottomRadius * math.cos(u * math.PI * 2.0),
+          _height * -0.5, _bottomRadius * math.sin(u * math.PI * 2.0));
     }
 
     // Top cap
     for (int x = 0; x < _segments; ++x) {
-      double u = x / _segments;
+      final double u = x / _segments;
 
-      positions[i++] = new Vector3(_topRadius * Math.cos(u * Math.PI * 2.0),
-          _height * 0.5, _topRadius * Math.sin(u * Math.PI * 2.0));
+      positions[i++] = new Vector3(_topRadius * math.cos(u * math.PI * 2.0),
+          _height * 0.5, _topRadius * math.sin(u * math.PI * 2.0));
     }
 
     // Bottom cap
     for (int x = 0; x < _segments; ++x) {
-      double u = x / _segments;
+      final double u = x / _segments;
 
-      positions[i++] = new Vector3(_bottomRadius * Math.cos(u * Math.PI * 2.0),
-          _height * -0.5, _bottomRadius * Math.sin(u * Math.PI * 2.0));
+      positions[i++] = new Vector3(_bottomRadius * math.cos(u * math.PI * 2.0),
+          _height * -0.5, _bottomRadius * math.sin(u * math.PI * 2.0));
     }
   }
 
+  @override
   void generateVertexTexCoords(
       Vector2List texCoords, Vector3List positions, Uint16List indices) {
     int i = 0;
 
     // Cylinder top
     for (int x = 0; x <= _segments; ++x) {
-      double u = 1.0 - (x / _segments);
+      final double u = 1.0 - (x / _segments);
       texCoords[i++] = new Vector2(u, 0.0);
     }
 
     // Cylinder bottom
     for (int x = 0; x <= _segments; ++x) {
-      double u = 1.0 - (x / _segments);
+      final double u = 1.0 - (x / _segments);
       texCoords[i++] = new Vector2(u, 1.0);
     }
 
     // Top cap
     for (int x = 0; x < _segments; ++x) {
-      double r = (x / _segments) * Math.PI * 2.0;
+      final double r = (x / _segments) * math.PI * 2.0;
       texCoords[i++] =
-          new Vector2((Math.cos(r) * 0.5 + 0.5), (Math.sin(r) * 0.5 + 0.5));
+          new Vector2((math.cos(r) * 0.5 + 0.5), (math.sin(r) * 0.5 + 0.5));
     }
 
     // Bottom cap
     for (int x = 0; x < _segments; ++x) {
-      double r = (x / _segments) * Math.PI * 2.0;
+      final double r = (x / _segments) * math.PI * 2.0;
       texCoords[i++] =
-          new Vector2((Math.cos(r) * 0.5 + 0.5), (Math.sin(r) * 0.5 + 0.5));
+          new Vector2((math.cos(r) * 0.5 + 0.5), (math.sin(r) * 0.5 + 0.5));
     }
   }
 }
diff --git a/pub/vector_math/lib/src/vector_math_geometry/generators/geometry_generator.dart b/pub/vector_math/lib/src/vector_math_geometry/generators/geometry_generator.dart
index 9f8d035..6a2171a 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/generators/geometry_generator.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/generators/geometry_generator.dart
@@ -18,8 +18,9 @@
   int get indexCount;
 
   MeshGeometry createGeometry(
-      {GeometryGeneratorFlags flags: null, List filters: null}) {
-    if (flags == null) flags = new GeometryGeneratorFlags();
+      {GeometryGeneratorFlags flags: null,
+      List<GeometryFilter> filters: null}) {
+    flags ??= new GeometryGeneratorFlags();
 
     VertexAttrib positionAttrib;
     VertexAttrib texCoordAttrib;
@@ -31,7 +32,7 @@
     Vector3List normalView;
     Vector4List tangentView;
 
-    List<VertexAttrib> attribs = new List<VertexAttrib>();
+    final List<VertexAttrib> attribs = <VertexAttrib>[];
 
     positionAttrib = new VertexAttrib('POSITION', 3, 'float');
     attribs.add(positionAttrib);
@@ -51,33 +52,44 @@
       attribs.add(tangentAttrib);
     }
 
-    MeshGeometry mesh = new MeshGeometry(vertexCount, attribs);
-
-    mesh.indices = new Uint16List(indexCount);
+    MeshGeometry mesh = new MeshGeometry(vertexCount, attribs)
+      ..indices = new Uint16List(indexCount);
     generateIndices(mesh.indices);
 
-    positionView = mesh.getViewForAttrib('POSITION');
-    generateVertexPositions(positionView, mesh.indices);
+    VectorList<Vector> view = mesh.getViewForAttrib('POSITION');
+    if (view is Vector3List) {
+      positionView = view;
+      generateVertexPositions(positionView, mesh.indices);
+    }
 
     if (flags.texCoords || flags.tangents) {
-      texCoordView = mesh.getViewForAttrib('TEXCOORD0');
-      generateVertexTexCoords(texCoordView, positionView, mesh.indices);
+      view = mesh.getViewForAttrib('TEXCOORD0');
+      if (view is Vector2List) {
+        texCoordView = view;
+        generateVertexTexCoords(texCoordView, positionView, mesh.indices);
+      }
     }
 
     if (flags.normals || flags.tangents) {
-      normalView = mesh.getViewForAttrib('NORMAL');
-      generateVertexNormals(normalView, positionView, mesh.indices);
+      view = mesh.getViewForAttrib('NORMAL');
+      if (view is Vector3List) {
+        normalView = view;
+        generateVertexNormals(normalView, positionView, mesh.indices);
+      }
     }
 
     if (flags.tangents) {
-      tangentView = mesh.getViewForAttrib('TANGENT');
-      generateVertexTangents(
-          tangentView, positionView, normalView, texCoordView, mesh.indices);
+      view = mesh.getViewForAttrib('TANGENT');
+      if (view is Vector4List) {
+        tangentView = view;
+        generateVertexTangents(
+            tangentView, positionView, normalView, texCoordView, mesh.indices);
+      }
     }
 
     if (filters != null) {
-      for (var filter in filters) {
-        if (filter.inplace) {
+      for (GeometryFilter filter in filters) {
+        if (filter.inplace && filter is InplaceGeometryFilter) {
           filter.filterInplace(mesh);
         } else {
           mesh = filter.filter(mesh);
@@ -95,7 +107,7 @@
   void generateVertexTexCoords(
       Vector2List texCoords, Vector3List positions, Uint16List indices) {
     for (int i = 0; i < positions.length; ++i) {
-      Vector3 p = positions[i];
+      final Vector3 p = positions[i];
 
       // These are TERRIBLE texture coords, but it's better than nothing.
       // Override this function and put better ones in place!
diff --git a/pub/vector_math/lib/src/vector_math_geometry/generators/ring_generator.dart b/pub/vector_math/lib/src/vector_math_geometry/generators/ring_generator.dart
index fa00860..d49bc71 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/generators/ring_generator.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/generators/ring_generator.dart
@@ -12,16 +12,19 @@
   double _thetaLength;
   bool _stripTextureCoordinates;
 
+  @override
   int get vertexCount => (_segments + 1) * 2;
+
+  @override
   int get indexCount => (_segments) * 3 * 2;
 
   MeshGeometry createRing(double innerRadius, double outerRadius,
-      {flags: null,
-      filters: null,
-      segments: 64,
-      thetaStart: 0.0,
-      thetaLength: Math.PI * 2.0,
-      stripTextureCoordinates: true}) {
+      {GeometryGeneratorFlags flags: null,
+      List<GeometryFilter> filters: null,
+      int segments: 64,
+      double thetaStart: 0.0,
+      double thetaLength: math.PI * 2.0,
+      bool stripTextureCoordinates: true}) {
     _innerRadius = innerRadius;
     _outerRadius = outerRadius;
     _segments = segments;
@@ -31,55 +34,63 @@
     return createGeometry(flags: flags, filters: filters);
   }
 
+  @override
   void generateVertexPositions(Vector3List positions, Uint16List indices) {
-    Vector3 v = new Vector3.zero();
+    final Vector3 v = new Vector3.zero();
     int index = 0;
     for (int i = 0; i <= _segments; i++) {
-      double percent = i / _segments;
-      v.x = _innerRadius * Math.cos(_thetaStart + percent * _thetaLength);
-      v.z = _innerRadius * Math.sin(_thetaStart + percent * _thetaLength);
+      final double percent = i / _segments;
+      v
+        ..x = _innerRadius * math.cos(_thetaStart + percent * _thetaLength)
+        ..z = _innerRadius * math.sin(_thetaStart + percent * _thetaLength);
       positions[index] = v;
       index++;
-      v.x = _outerRadius * Math.cos(_thetaStart + percent * _thetaLength);
-      v.z = _outerRadius * Math.sin(_thetaStart + percent * _thetaLength);
+      v
+        ..x = _outerRadius * math.cos(_thetaStart + percent * _thetaLength)
+        ..z = _outerRadius * math.sin(_thetaStart + percent * _thetaLength);
       positions[index] = v;
       index++;
     }
     assert(index == vertexCount);
   }
 
+  @override
   void generateVertexTexCoords(
       Vector2List texCoords, Vector3List positions, Uint16List indices) {
     if (_stripTextureCoordinates) {
-      Vector2 v = new Vector2.zero();
+      final Vector2 v = new Vector2.zero();
       int index = 0;
       for (int i = 0; i <= _segments; i++) {
-        double percent = i / _segments;
-        v.x = 0.0;
-        v.y = percent;
+        final double percent = i / _segments;
+        v
+          ..x = 0.0
+          ..y = percent;
         texCoords[index] = v;
         index++;
-        v.x = 1.0;
-        v.y = percent;
+        v
+          ..x = 1.0
+          ..y = percent;
         texCoords[index] = v;
         index++;
       }
     } else {
-      Vector2 v = new Vector2.zero();
+      final Vector2 v = new Vector2.zero();
       int index = 0;
       for (int i = 0; i <= _segments; i++) {
         Vector3 position = positions[index];
         double x = (position.x / (_outerRadius + 1.0)) * 0.5;
         double y = (position.z / (_outerRadius + 1.0)) * 0.5;
-        v.x = x + 0.5;
-        v.y = y + 0.5;
+        v
+          ..x = x + 0.5
+          ..y = y + 0.5;
         texCoords[index] = v;
         index++;
         position = positions[index];
         x = (position.x / (_outerRadius + 1.0)) * 0.5;
         y = (position.z / (_outerRadius + 1.0)) * 0.5;
-        v.x = x + 0.5;
-        v.y = y + 0.5;
+        v
+          ..x = x + 0.5
+          ..y = y + 0.5;
         texCoords[index] = v;
         index++;
       }
@@ -87,9 +98,10 @@
     }
   }
 
+  @override
   void generateIndices(Uint16List indices) {
     int index = 0;
-    int length = _segments * 2;
+    final int length = _segments * 2;
     for (int i = 0; i < length; i += 2) {
       indices[index + 0] = i + 0;
       indices[index + 1] = i + 1;
diff --git a/pub/vector_math/lib/src/vector_math_geometry/generators/sphere_generator.dart b/pub/vector_math/lib/src/vector_math_geometry/generators/sphere_generator.dart
index e7d15e3..fdb4eca 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/generators/sphere_generator.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/generators/sphere_generator.dart
@@ -9,11 +9,17 @@
   int _latSegments;
   int _lonSegments;
 
+  @override
   int get vertexCount => (_lonSegments + 1) * (_latSegments + 1);
+
+  @override
   int get indexCount => 6 * _lonSegments * _latSegments;
 
   MeshGeometry createSphere(num radius,
-      {int latSegments: 16, int lonSegments: 16, flags: null, filters: null}) {
+      {int latSegments: 16,
+      int lonSegments: 16,
+      GeometryGeneratorFlags flags: null,
+      List<GeometryFilter> filters: null}) {
     _radius = radius.toDouble();
     _latSegments = latSegments;
     _lonSegments = lonSegments;
@@ -21,11 +27,12 @@
     return createGeometry(flags: flags, filters: filters);
   }
 
+  @override
   void generateIndices(Uint16List indices) {
     int i = 0;
     for (int y = 0; y < _latSegments; ++y) {
-      int base1 = (_lonSegments + 1) * y;
-      int base2 = (_lonSegments + 1) * (y + 1);
+      final int base1 = (_lonSegments + 1) * y;
+      final int base2 = (_lonSegments + 1) * (y + 1);
 
       for (int x = 0; x < _lonSegments; ++x) {
         indices[i++] = base1 + x;
@@ -39,48 +46,51 @@
     }
   }
 
+  @override
   void generateVertexPositions(Vector3List positions, Uint16List indices) {
     int i = 0;
     for (int y = 0; y <= _latSegments; ++y) {
-      double v = y / _latSegments;
-      double sv = Math.sin(v * Math.PI);
-      double cv = Math.cos(v * Math.PI);
+      final double v = y / _latSegments;
+      final double sv = math.sin(v * math.PI);
+      final double cv = math.cos(v * math.PI);
 
       for (int x = 0; x <= _lonSegments; ++x) {
-        double u = x / _lonSegments;
+        final double u = x / _lonSegments;
 
-        positions[i++] = new Vector3(_radius * Math.cos(u * Math.PI * 2.0) * sv,
-            _radius * cv, _radius * Math.sin(u * Math.PI * 2.0) * sv);
+        positions[i++] = new Vector3(_radius * math.cos(u * math.PI * 2.0) * sv,
+            _radius * cv, _radius * math.sin(u * math.PI * 2.0) * sv);
       }
     }
   }
 
+  @override
   void generateVertexTexCoords(
       Vector2List texCoords, Vector3List positions, Uint16List indices) {
     int i = 0;
     for (int y = 0; y <= _latSegments; ++y) {
-      double v = y / _latSegments;
+      final double v = y / _latSegments;
 
       for (int x = 0; x <= _lonSegments; ++x) {
-        double u = x / _lonSegments;
+        final double u = x / _lonSegments;
         texCoords[i++] = new Vector2(u, v);
       }
     }
   }
 
+  @override
   void generateVertexNormals(
       Vector3List normals, Vector3List positions, Uint16List indices) {
     int i = 0;
     for (int y = 0; y <= _latSegments; ++y) {
-      double v = y / _latSegments;
-      double sv = Math.sin(v * Math.PI);
-      double cv = Math.cos(v * Math.PI);
+      final double v = y / _latSegments;
+      final double sv = math.sin(v * math.PI);
+      final double cv = math.cos(v * math.PI);
 
       for (int x = 0; x <= _lonSegments; ++x) {
-        double u = x / _lonSegments;
+        final double u = x / _lonSegments;
 
-        normals[i++] = new Vector3(Math.cos(u * Math.PI * 2.0) * sv, cv,
-            Math.sin(u * Math.PI * 2.0) * sv);
+        normals[i++] = new Vector3(math.cos(u * math.PI * 2.0) * sv, cv,
+            math.sin(u * math.PI * 2.0) * sv);
       }
     }
   }
diff --git a/pub/vector_math/lib/src/vector_math_geometry/mesh_geometry.dart b/pub/vector_math/lib/src/vector_math_geometry/mesh_geometry.dart
index 314b61e..5eedb53 100644
--- a/pub/vector_math/lib/src/vector_math_geometry/mesh_geometry.dart
+++ b/pub/vector_math/lib/src/vector_math_geometry/mesh_geometry.dart
@@ -30,9 +30,9 @@
         size = attrib.size,
         type = attrib.type;
 
-  VectorList getView(Float32List buffer) {
-    int viewOffset = offset ~/ buffer.elementSizeInBytes;
-    int viewStride = stride ~/ buffer.elementSizeInBytes;
+  VectorList<Vector> getView(Float32List buffer) {
+    final int viewOffset = offset ~/ buffer.elementSizeInBytes;
+    final int viewStride = stride ~/ buffer.elementSizeInBytes;
     switch (size) {
       case 2:
         return new Vector2List.view(buffer, viewOffset, viewStride);
@@ -45,9 +45,7 @@
     }
   }
 
-  String get format {
-    return '$type$size';
-  }
+  String get format => '$type$size';
 
   int get elementSize {
     switch (type) {
@@ -63,16 +61,14 @@
     }
   }
 
-  Map toJson() {
-    return {
-      'format': format,
-      'name': name,
-      'offset': offset,
-      'stride': stride,
-      'size': size,
-      'type': type
-    };
-  }
+  Map<String, Object> toJson() => <String, Object>{
+        'format': format,
+        'name': name,
+        'offset': offset,
+        'stride': stride,
+        'size': size,
+        'type': type
+      };
 }
 
 class MeshGeometry {
@@ -88,7 +84,7 @@
       stride += a.elementSize * a.size;
     }
     int offset = 0;
-    List<VertexAttrib> attribs = new List<VertexAttrib>();
+    final List<VertexAttrib> attribs = <VertexAttrib>[];
     for (VertexAttrib a in attributes) {
       attribs.add(new VertexAttrib._resetStrideOffset(a, stride, offset));
       offset += a.elementSize * a.size;
@@ -97,8 +93,7 @@
     return new MeshGeometry._internal(length, stride, attribs);
   }
 
-  MeshGeometry._internal(
-      int this.length, int this.stride, List<VertexAttrib> this.attribs,
+  MeshGeometry._internal(this.length, this.stride, this.attribs,
       [Float32List externBuffer]) {
     if (externBuffer == null) {
       buffer =
@@ -123,27 +118,44 @@
     }
   }
 
-  int get triangleVertexCount => indices != null ? indices.length : length;
+  factory MeshGeometry.fromJson(Map<String, Object> json) {
+    Float32List buffer;
+    final Object jsonBuffer = json["buffer"];
+    if (jsonBuffer is List<double>) {
+      buffer = new Float32List.fromList(jsonBuffer);
+    } else {
+      throw new ArgumentError.value(
+          jsonBuffer, 'json["buffer"]', 'Value type must be List<double>');
+    }
 
-  factory MeshGeometry.fromJson(Map json) {
-    Float32List buffer = new Float32List.fromList(json["buffer"]);
-
-    Map jsonAttribs = json["attribs"];
+    final Object jsonAttribs = json["attribs"];
+    Map<String, Object> jsonAttribsMap;
+    if (jsonAttribs is Map<String, Object>) {
+      jsonAttribsMap = jsonAttribs;
+    } else {
+      throw new ArgumentError.value(jsonBuffer, 'json["attribs"]',
+          'Value type must be Map<String, Object>');
+    }
     List<VertexAttrib> attribs;
     int stride = 0;
-    for (String key in jsonAttribs.keys) {
-      VertexAttrib attrib = attribFromJson(key, jsonAttribs[key]);
-      attribs.add(attrib);
-      if (stride == 0) {
-        stride = attrib.stride;
+    for (String key in jsonAttribsMap.keys) {
+      VertexAttrib attrib;
+      final Object jsonAttrib = jsonAttribsMap[key];
+      if (jsonAttrib is Map<String, Object>) {
+        attrib = attribFromJson(key, jsonAttrib);
+        attribs.add(attrib);
+        if (stride == 0) {
+          stride = attrib.stride;
+        }
       }
     }
 
-    MeshGeometry mesh = new MeshGeometry._internal(
+    final MeshGeometry mesh = new MeshGeometry._internal(
         buffer.lengthInBytes ~/ stride, stride, attribs, buffer);
 
-    if (json.containsKey("indices")) {
-      mesh.indices = new Uint16List.fromList(json["indices"]);
+    final Object jsonIndices = json["indices"];
+    if (jsonIndices is List<int>) {
+      mesh.indices = new Uint16List.fromList(jsonIndices);
     }
 
     return mesh;
@@ -151,12 +163,12 @@
 
   factory MeshGeometry.resetAttribs(
       MeshGeometry inputMesh, List<VertexAttrib> attributes) {
-    MeshGeometry mesh = new MeshGeometry(inputMesh.length, attributes);
-    mesh.indices = inputMesh.indices;
+    final MeshGeometry mesh = new MeshGeometry(inputMesh.length, attributes)
+      ..indices = inputMesh.indices;
 
     // Copy over the attributes that were specified
     for (VertexAttrib attrib in mesh.attribs) {
-      VertexAttrib inputAttrib = inputMesh.getAttrib(attrib.name);
+      final VertexAttrib inputAttrib = inputMesh.getAttrib(attrib.name);
       if (inputAttrib != null) {
         if (inputAttrib.size != attrib.size ||
             inputAttrib.type != attrib.type) {
@@ -164,9 +176,11 @@
               "Attributes size or type is mismatched: ${attrib.name}");
         }
 
-        var inputView = inputAttrib.getView(inputMesh.buffer);
-        var outputView = attrib.getView(mesh.buffer);
-        outputView.copy(inputView);
+        final VectorList<Vector> inputView =
+            inputAttrib.getView(inputMesh.buffer);
+
+        // Copy [inputView] to a view from attrib
+        attrib.getView(mesh.buffer).copy(inputView);
       }
     }
 
@@ -180,11 +194,11 @@
     }
 
     // When combining meshes they must all have a matching set of VertexAttribs
-    MeshGeometry firstMesh = meshes[0];
+    final MeshGeometry firstMesh = meshes[0];
     int totalVerts = firstMesh.length;
     int totalIndices = firstMesh.indices != null ? firstMesh.indices.length : 0;
     for (int i = 1; i < meshes.length; ++i) {
-      MeshGeometry srcMesh = meshes[i];
+      final MeshGeometry srcMesh = meshes[i];
       if (!firstMesh.attribsAreCompatible(srcMesh)) {
         throw new Exception(
             "All meshes must have identical attributes to combine.");
@@ -193,7 +207,7 @@
       totalIndices += srcMesh.indices != null ? srcMesh.indices.length : 0;
     }
 
-    MeshGeometry mesh = new MeshGeometry._internal(
+    final MeshGeometry mesh = new MeshGeometry._internal(
         totalVerts, firstMesh.stride, firstMesh.attribs);
 
     if (totalIndices > 0) {
@@ -204,7 +218,7 @@
     int bufferOffset = 0;
     int indexOffset = 0;
     for (int i = 0; i < meshes.length; ++i) {
-      MeshGeometry srcMesh = meshes[i];
+      final MeshGeometry srcMesh = meshes[i];
       mesh.buffer.setAll(bufferOffset, srcMesh.buffer);
 
       if (totalIndices > 0) {
@@ -220,29 +234,46 @@
     return mesh;
   }
 
-  Map toJson() {
-    Map r = {};
+  int get triangleVertexCount => indices != null ? indices.length : length;
+
+  Map<String, Object> toJson() {
+    final Map<String, Object> r = <String, Object>{};
     r['attributes'] = attribs;
     r['indices'] = indices;
     r['vertices'] = buffer;
     return r;
   }
 
-  static VertexAttrib attribFromJson(String name, Map json) {
-    return new VertexAttrib._internal(
-        name, json["size"], json["type"], json["stride"], json["offset"]);
+  static VertexAttrib attribFromJson(String name, Map<String, Object> json) {
+    final Object jsonSize = json["size"];
+    final Object jsonType = json["type"];
+    final Object jsonStride = json["stride"];
+    final Object jsonOffset = json["offset"];
+    if (jsonSize is int &&
+        jsonType is String &&
+        jsonStride is int &&
+        jsonOffset is int) {
+      return new VertexAttrib._internal(
+          name, jsonSize, jsonType, jsonStride, jsonOffset);
+    } else {
+      return null;
+    }
   }
 
   VertexAttrib getAttrib(String name) {
     for (VertexAttrib attrib in attribs) {
-      if (attrib.name == name) return attrib;
+      if (attrib.name == name) {
+        return attrib;
+      }
     }
     return null;
   }
 
-  VectorList getViewForAttrib(String name) {
+  VectorList<Vector> getViewForAttrib(String name) {
     for (VertexAttrib attrib in attribs) {
-      if (attrib.name == name) return attrib.getView(buffer);
+      if (attrib.name == name) {
+        return attrib.getView(buffer);
+      }
     }
     return null;
   }
@@ -253,7 +284,7 @@
     }
 
     for (VertexAttrib attrib in attribs) {
-      VertexAttrib otherAttrib = mesh.getAttrib(attrib.name);
+      final VertexAttrib otherAttrib = mesh.getAttrib(attrib.name);
       if (otherAttrib == null) {
         return false;
       }
diff --git a/pub/vector_math/lib/src/vector_math_lists/scalar_list_view.dart b/pub/vector_math/lib/src/vector_math_lists/scalar_list_view.dart
index 499e555..7c7cc4f 100644
--- a/pub/vector_math/lib/src/vector_math_lists/scalar_list_view.dart
+++ b/pub/vector_math/lib/src/vector_math_lists/scalar_list_view.dart
@@ -19,7 +19,7 @@
   Float32List get buffer => _buffer;
 
   static int _listLength(int offset, int stride, int length) {
-    int width = stride == 0 ? 1 : stride;
+    final int width = stride == 0 ? 1 : stride;
     return offset + width * length;
   }
 
@@ -51,13 +51,11 @@
   ScalarListView.view(Float32List buffer, [int offset = 0, int stride = 0])
       : _offset = offset,
         _stride = stride == 0 ? 1 : stride,
-        _length = (buffer.length - Math.max(0, offset - stride)) ~/
+        _length = (buffer.length - math.max(0, offset - stride)) ~/
             (stride == 0 ? 1 : stride),
         _buffer = buffer;
 
-  int _elementIndexToBufferIndex(int index) {
-    return _offset + _stride * index;
-  }
+  int _elementIndexToBufferIndex(int index) => _offset + _stride * index;
 
   /// Retrieves the value at [index].
   double operator [](int index) => load(index);
@@ -69,7 +67,7 @@
 
   /// Store [value] in the list at [index].
   void store(int index, double value) {
-    final i = _elementIndexToBufferIndex(index);
+    final int i = _elementIndexToBufferIndex(index);
     _buffer[i] = value;
   }
 
diff --git a/pub/vector_math/lib/src/vector_math_lists/vector2_list.dart b/pub/vector_math/lib/src/vector_math_lists/vector2_list.dart
index a84fc15..df1eabe 100644
--- a/pub/vector_math/lib/src/vector_math_lists/vector2_list.dart
+++ b/pub/vector_math/lib/src/vector_math_lists/vector2_list.dart
@@ -22,21 +22,21 @@
       : super.view(buffer, 2, offset, stride);
 
   @override
-  Vector2 newVector() {
-    return new Vector2.zero();
-  }
+  Vector2 newVector() => new Vector2.zero();
 
   /// Retrieves the vector at [index] and stores it in [vector].
+  @override
   void load(int index, Vector2 vector) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     vector.storage[0] = _buffer[i + 0];
     vector.storage[1] = _buffer[i + 1];
   }
 
   /// Store [vector] in the list at [index].
+  @override
   void store(int index, Vector2 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     _buffer[i + 0] = storage[0];
     _buffer[i + 1] = storage[1];
   }
@@ -46,46 +46,46 @@
 
   /// Set the vector at [index] to [x] and [y].
   void setValues(int index, double x, double y) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     buffer[i + 0] = x;
     buffer[i + 1] = y;
   }
 
   /// Add [vector] to the vector at [index].
   void add(int index, Vector2 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] += storage[0];
     buffer[i + 1] += storage[1];
   }
 
   /// Add [vector] scaled by [factor] to the vector at [index].
   void addScaled(int index, Vector2 vector, double factor) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] += storage[0] * factor;
     buffer[i + 1] += storage[1] * factor;
   }
 
   /// Substract [vector] from the vector at [index].
   void sub(int index, Vector2 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] -= storage[0];
     buffer[i + 1] -= storage[1];
   }
 
   /// Multiply the vector at [index] by [vector].
   void multiply(int index, Vector2 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] *= storage[0];
     buffer[i + 1] *= storage[1];
   }
 
   /// Scale the vector at [index] by [factor].
   void scale(int index, double factor) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     buffer[i + 0] *= factor;
     buffer[i + 1] *= factor;
   }
diff --git a/pub/vector_math/lib/src/vector_math_lists/vector3_list.dart b/pub/vector_math/lib/src/vector_math_lists/vector3_list.dart
index c75c6ce..bd99b18 100644
--- a/pub/vector_math/lib/src/vector_math_lists/vector3_list.dart
+++ b/pub/vector_math/lib/src/vector_math_lists/vector3_list.dart
@@ -22,22 +22,22 @@
       : super.view(buffer, 3, offset, stride);
 
   @override
-  Vector3 newVector() {
-    return new Vector3.zero();
-  }
+  Vector3 newVector() => new Vector3.zero();
 
   /// Retrieves the vector at [index] and stores it in [vector].
+  @override
   void load(int index, Vector3 vector) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     vector.storage[0] = _buffer[i + 0];
     vector.storage[1] = _buffer[i + 1];
     vector.storage[2] = _buffer[i + 2];
   }
 
   /// Store [vector] in the list at [index].
+  @override
   void store(int index, Vector3 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     _buffer[i + 0] = storage[0];
     _buffer[i + 1] = storage[1];
     _buffer[i + 2] = storage[2];
@@ -48,7 +48,7 @@
 
   /// Set the vector at [index] to [x], [y], and [z].
   void setValues(int index, double x, double y, double z) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     buffer[i + 0] = x;
     buffer[i + 1] = y;
     buffer[i + 2] = z;
@@ -56,8 +56,8 @@
 
   /// Add [vector] to the vector at [index].
   void add(int index, Vector3 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] += storage[0];
     buffer[i + 1] += storage[1];
     buffer[i + 2] += storage[2];
@@ -65,8 +65,8 @@
 
   /// Add [vector] scaled by [factor] to the vector at [index].
   void addScaled(int index, Vector3 vector, double factor) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] += storage[0] * factor;
     buffer[i + 1] += storage[1] * factor;
     buffer[i + 2] += storage[2] * factor;
@@ -74,8 +74,8 @@
 
   /// Substract [vector] from the vector at [index].
   void sub(int index, Vector3 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] -= storage[0];
     buffer[i + 1] -= storage[1];
     buffer[i + 2] -= storage[2];
@@ -83,8 +83,8 @@
 
   /// Multiply the vector at [index] by [vector].
   void multiply(int index, Vector3 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] *= storage[0];
     buffer[i + 1] *= storage[1];
     buffer[i + 2] *= storage[2];
@@ -92,7 +92,7 @@
 
   /// Scale the vector at [index] by [factor].
   void scale(int index, double factor) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     buffer[i + 0] *= factor;
     buffer[i + 1] *= factor;
     buffer[i + 2] *= factor;
diff --git a/pub/vector_math/lib/src/vector_math_lists/vector4_list.dart b/pub/vector_math/lib/src/vector_math_lists/vector4_list.dart
index 6b26112..09c16d1 100644
--- a/pub/vector_math/lib/src/vector_math_lists/vector4_list.dart
+++ b/pub/vector_math/lib/src/vector_math_lists/vector4_list.dart
@@ -22,13 +22,12 @@
       : super.view(buffer, 4, offset, stride);
 
   @override
-  Vector4 newVector() {
-    return new Vector4.zero();
-  }
+  Vector4 newVector() => new Vector4.zero();
 
   /// Retrieves the vector at [index] and stores it in [vector].
+  @override
   void load(int index, Vector4 vector) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     vector.storage[0] = _buffer[i + 0];
     vector.storage[1] = _buffer[i + 1];
     vector.storage[2] = _buffer[i + 2];
@@ -36,9 +35,10 @@
   }
 
   /// Store [vector] in the list at [index].
+  @override
   void store(int index, Vector4 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     _buffer[i + 0] = storage[0];
     _buffer[i + 1] = storage[1];
     _buffer[i + 2] = storage[2];
@@ -50,7 +50,7 @@
 
   /// Set the vector at [index] to [x], [y], [z], and [w].
   void setValues(int index, double x, double y, double z, double w) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     buffer[i + 0] = x;
     buffer[i + 1] = y;
     buffer[i + 2] = z;
@@ -59,8 +59,8 @@
 
   /// Add [vector] to the vector at [index].
   void add(int index, Vector4 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] += storage[0];
     buffer[i + 1] += storage[1];
     buffer[i + 2] += storage[2];
@@ -69,8 +69,8 @@
 
   /// Add [vector] scaled by [factor] to the vector at [index].
   void addScaled(int index, Vector4 vector, double factor) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] += storage[0] * factor;
     buffer[i + 1] += storage[1] * factor;
     buffer[i + 2] += storage[2] * factor;
@@ -79,8 +79,8 @@
 
   /// Substract [vector] from the vector at [index].
   void sub(int index, Vector4 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] -= storage[0];
     buffer[i + 1] -= storage[1];
     buffer[i + 2] -= storage[2];
@@ -89,8 +89,8 @@
 
   /// Multiply the vector at [index] by [vector].
   void multiply(int index, Vector4 vector) {
-    final i = _vectorIndexToBufferIndex(index);
-    final storage = vector.storage;
+    final int i = _vectorIndexToBufferIndex(index);
+    final Float32List storage = vector.storage;
     buffer[i + 0] *= storage[0];
     buffer[i + 1] *= storage[1];
     buffer[i + 2] *= storage[2];
@@ -99,7 +99,7 @@
 
   /// Scale the vector at [index] by [factor].
   void scale(int index, double factor) {
-    final i = _vectorIndexToBufferIndex(index);
+    final int i = _vectorIndexToBufferIndex(index);
     buffer[i + 0] *= factor;
     buffer[i + 1] *= factor;
     buffer[i + 2] *= factor;
diff --git a/pub/vector_math/lib/src/vector_math_lists/vector_list.dart b/pub/vector_math/lib/src/vector_math_lists/vector_list.dart
index a92fd33..d77256a 100644
--- a/pub/vector_math/lib/src/vector_math_lists/vector_list.dart
+++ b/pub/vector_math/lib/src/vector_math_lists/vector_list.dart
@@ -20,7 +20,7 @@
   Float32List get buffer => _buffer;
 
   static int _listLength(int offset, int stride, int vectorLength, int length) {
-    int width = stride == 0 ? vectorLength : stride;
+    final int width = stride == 0 ? vectorLength : stride;
     return offset + width * length;
   }
 
@@ -42,7 +42,7 @@
   /// Create a new vector list from a list of vectors that have a size of
   /// [vectorLength]. Optionally it is possible to specify an [offset] in the
   /// [buffer] and a [stride] between each vector.
-  VectorList.fromList(List list, int vectorLength,
+  VectorList.fromList(List<T> list, int vectorLength,
       [int offset = 0, int stride = 0])
       : _vectorLength = vectorLength,
         _offset = offset,
@@ -66,7 +66,7 @@
       : _vectorLength = vectorLength,
         _offset = offset,
         _stride = stride == 0 ? vectorLength : stride,
-        _length = (buffer.length - Math.max(0, offset - stride)) ~/
+        _length = (buffer.length - math.max(0, offset - stride)) ~/
             (stride == 0 ? vectorLength : stride),
         _buffer = buffer {
     if (_stride < _vectorLength) {
@@ -74,9 +74,7 @@
     }
   }
 
-  int _vectorIndexToBufferIndex(int index) {
-    return _offset + _stride * index;
-  }
+  int _vectorIndexToBufferIndex(int index) => _offset + _stride * index;
 
   /// Create a new instance of [T].
   T newVector();
@@ -89,11 +87,12 @@
 
   /// Copy a range of [count] vectors beginning at [srcOffset] from [src] into
   /// this list starting at [offset].
-  void copy(VectorList src, {int srcOffset: 0, int offset: 0, int count: 0}) {
+  void copy(VectorList<T> src,
+      {int srcOffset: 0, int offset: 0, int count: 0}) {
     if (count == 0) {
-      count = Math.min(length - offset, src.length - srcOffset);
+      count = math.min(length - offset, src.length - srcOffset);
     }
-    int minVectorLength = Math.min(_vectorLength, src._vectorLength);
+    final int minVectorLength = math.min(_vectorLength, src._vectorLength);
     for (int i = 0; i < count; i++) {
       int index = _vectorIndexToBufferIndex(i + offset);
       int srcIndex = src._vectorIndexToBufferIndex(i + srcOffset);
@@ -105,7 +104,7 @@
 
   /// Retrieves the vector at [index].
   T operator [](int index) {
-    var r = newVector();
+    final T r = newVector();
     load(index, r);
     return r;
   }
diff --git a/pub/vector_math/lib/src/vector_math_operations/matrix.dart b/pub/vector_math/lib/src/vector_math_operations/matrix.dart
index f00d207..d893325 100644
--- a/pub/vector_math/lib/src/vector_math_operations/matrix.dart
+++ b/pub/vector_math/lib/src/vector_math_operations/matrix.dart
@@ -9,36 +9,40 @@
 class Matrix44Operations {
   /// Compute the determinant of the 4x4 [matrix] starting at [offset].
   static double determinant(Float32List matrix, int offset) {
-    double m0 = matrix[0 + offset];
-    double m1 = matrix[1 + offset];
-    double m2 = matrix[2 + offset];
-    double m3 = matrix[3 + offset];
-    double m4 = matrix[4 + offset];
-    double m5 = matrix[5 + offset];
-    double m6 = matrix[6 + offset];
-    double m7 = matrix[7 + offset];
+    final double m0 = matrix[0 + offset];
+    final double m1 = matrix[1 + offset];
+    final double m2 = matrix[2 + offset];
+    final double m3 = matrix[3 + offset];
+    final double m4 = matrix[4 + offset];
+    final double m5 = matrix[5 + offset];
+    final double m6 = matrix[6 + offset];
+    final double m7 = matrix[7 + offset];
 
-    double det2_01_01 = m0 * m5 - m1 * m4;
-    double det2_01_02 = m0 * m6 - m2 * m4;
-    double det2_01_03 = m0 * m7 - m3 * m4;
-    double det2_01_12 = m1 * m6 - m2 * m5;
-    double det2_01_13 = m1 * m7 - m3 * m5;
-    double det2_01_23 = m2 * m7 - m3 * m6;
+    final double det2_01_01 = m0 * m5 - m1 * m4;
+    final double det2_01_02 = m0 * m6 - m2 * m4;
+    final double det2_01_03 = m0 * m7 - m3 * m4;
+    final double det2_01_12 = m1 * m6 - m2 * m5;
+    final double det2_01_13 = m1 * m7 - m3 * m5;
+    final double det2_01_23 = m2 * m7 - m3 * m6;
 
-    double m8 = matrix[8 + offset];
-    double m9 = matrix[9 + offset];
-    double m10 = matrix[10 + offset];
-    double m11 = matrix[11 + offset];
+    final double m8 = matrix[8 + offset];
+    final double m9 = matrix[9 + offset];
+    final double m10 = matrix[10 + offset];
+    final double m11 = matrix[11 + offset];
 
-    double det3_201_012 = m8 * det2_01_12 - m9 * det2_01_02 + m10 * det2_01_01;
-    double det3_201_013 = m8 * det2_01_13 - m9 * det2_01_03 + m11 * det2_01_01;
-    double det3_201_023 = m8 * det2_01_23 - m10 * det2_01_03 + m11 * det2_01_02;
-    double det3_201_123 = m9 * det2_01_23 - m10 * det2_01_13 + m11 * det2_01_12;
+    final double det3_201_012 =
+        m8 * det2_01_12 - m9 * det2_01_02 + m10 * det2_01_01;
+    final double det3_201_013 =
+        m8 * det2_01_13 - m9 * det2_01_03 + m11 * det2_01_01;
+    final double det3_201_023 =
+        m8 * det2_01_23 - m10 * det2_01_03 + m11 * det2_01_02;
+    final double det3_201_123 =
+        m9 * det2_01_23 - m10 * det2_01_13 + m11 * det2_01_12;
 
-    double m12 = matrix[12 + offset];
-    double m13 = matrix[13 + offset];
-    double m14 = matrix[14 + offset];
-    double m15 = matrix[15 + offset];
+    final double m12 = matrix[12 + offset];
+    final double m13 = matrix[13 + offset];
+    final double m14 = matrix[14 + offset];
+    final double m15 = matrix[15 + offset];
 
     return -det3_201_123 * m12 +
         det3_201_023 * m13 -
@@ -49,59 +53,59 @@
   /// Compute the determinant of the upper 3x3 of the 4x4 [matrix] starting at
   /// [offset].
   static double determinant33(Float32List matrix, int offset) {
-    double m0 = matrix[0 + offset];
-    double m1 = matrix[1 + offset];
-    double m2 = matrix[2 + offset];
-    double m4 = matrix[4 + offset];
-    double m5 = matrix[5 + offset];
-    double m6 = matrix[6 + offset];
-    double m8 = matrix[8 + offset];
-    double m9 = matrix[9 + offset];
-    double m10 = matrix[10 + offset];
-    double x = m0 * ((m5 * m10) - (m6 * m8));
-    double y = m1 * ((m4 * m10) - (m6 * m8));
-    double z = m2 * ((m4 * m9) - (m5 * m8));
+    final double m0 = matrix[0 + offset];
+    final double m1 = matrix[1 + offset];
+    final double m2 = matrix[2 + offset];
+    final double m4 = matrix[4 + offset];
+    final double m5 = matrix[5 + offset];
+    final double m6 = matrix[6 + offset];
+    final double m8 = matrix[8 + offset];
+    final double m9 = matrix[9 + offset];
+    final double m10 = matrix[10 + offset];
+    final double x = m0 * ((m5 * m10) - (m6 * m8));
+    final double y = m1 * ((m4 * m10) - (m6 * m8));
+    final double z = m2 * ((m4 * m9) - (m5 * m8));
     return x - y + z;
   }
 
   /// Compute the inverse of the 4x4 [matrix] starting at [offset].
   static double inverse(Float32List matrix, int offset) {
-    double a00 = matrix[0];
-    double a01 = matrix[1];
-    double a02 = matrix[2];
-    double a03 = matrix[3];
-    double a10 = matrix[4];
-    double a11 = matrix[5];
-    double a12 = matrix[6];
-    double a13 = matrix[7];
-    double a20 = matrix[8];
-    double a21 = matrix[9];
-    double a22 = matrix[10];
-    double a23 = matrix[11];
-    double a30 = matrix[12];
-    double a31 = matrix[13];
-    double a32 = matrix[14];
-    double a33 = matrix[15];
-    double b00 = a00 * a11 - a01 * a10;
-    double b01 = a00 * a12 - a02 * a10;
-    double b02 = a00 * a13 - a03 * a10;
-    double b03 = a01 * a12 - a02 * a11;
-    double b04 = a01 * a13 - a03 * a11;
-    double b05 = a02 * a13 - a03 * a12;
-    double b06 = a20 * a31 - a21 * a30;
-    double b07 = a20 * a32 - a22 * a30;
-    double b08 = a20 * a33 - a23 * a30;
-    double b09 = a21 * a32 - a22 * a31;
-    double b10 = a21 * a33 - a23 * a31;
-    double b11 = a22 * a33 - a23 * a32;
-    double det =
+    final double a00 = matrix[0];
+    final double a01 = matrix[1];
+    final double a02 = matrix[2];
+    final double a03 = matrix[3];
+    final double a10 = matrix[4];
+    final double a11 = matrix[5];
+    final double a12 = matrix[6];
+    final double a13 = matrix[7];
+    final double a20 = matrix[8];
+    final double a21 = matrix[9];
+    final double a22 = matrix[10];
+    final double a23 = matrix[11];
+    final double a30 = matrix[12];
+    final double a31 = matrix[13];
+    final double a32 = matrix[14];
+    final double a33 = matrix[15];
+    final double b00 = a00 * a11 - a01 * a10;
+    final double b01 = a00 * a12 - a02 * a10;
+    final double b02 = a00 * a13 - a03 * a10;
+    final double b03 = a01 * a12 - a02 * a11;
+    final double b04 = a01 * a13 - a03 * a11;
+    final double b05 = a02 * a13 - a03 * a12;
+    final double b06 = a20 * a31 - a21 * a30;
+    final double b07 = a20 * a32 - a22 * a30;
+    final double b08 = a20 * a33 - a23 * a30;
+    final double b09 = a21 * a32 - a22 * a31;
+    final double b10 = a21 * a33 - a23 * a31;
+    final double b11 = a22 * a33 - a23 * a32;
+    final double det =
         (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
 
     if (det == 0.0) {
       return det;
     }
 
-    var invDet = 1.0 / det;
+    final double invDet = 1.0 / det;
 
     matrix[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
     matrix[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
@@ -131,27 +135,27 @@
   /// [out] = [a] * [b]; Starting at [outOffset], [aOffset], and [bOffset].
   static void multiply(Float32List out, int outOffset, Float32List a,
       int aOffset, Float32List b, int bOffset) {
-    var a00 = a[aOffset++];
-    var a01 = a[aOffset++];
-    var a02 = a[aOffset++];
-    var a03 = a[aOffset++];
-    var a10 = a[aOffset++];
-    var a11 = a[aOffset++];
-    var a12 = a[aOffset++];
-    var a13 = a[aOffset++];
-    var a20 = a[aOffset++];
-    var a21 = a[aOffset++];
-    var a22 = a[aOffset++];
-    var a23 = a[aOffset++];
-    var a30 = a[aOffset++];
-    var a31 = a[aOffset++];
-    var a32 = a[aOffset++];
-    var a33 = a[aOffset++];
+    final double a00 = a[aOffset++];
+    final double a01 = a[aOffset++];
+    final double a02 = a[aOffset++];
+    final double a03 = a[aOffset++];
+    final double a10 = a[aOffset++];
+    final double a11 = a[aOffset++];
+    final double a12 = a[aOffset++];
+    final double a13 = a[aOffset++];
+    final double a20 = a[aOffset++];
+    final double a21 = a[aOffset++];
+    final double a22 = a[aOffset++];
+    final double a23 = a[aOffset++];
+    final double a30 = a[aOffset++];
+    final double a31 = a[aOffset++];
+    final double a32 = a[aOffset++];
+    final double a33 = a[aOffset++];
 
-    var b0 = b[bOffset++];
-    var b1 = b[bOffset++];
-    var b2 = b[bOffset++];
-    var b3 = b[bOffset++];
+    double b0 = b[bOffset++];
+    double b1 = b[bOffset++];
+    double b2 = b[bOffset++];
+    double b3 = b[bOffset++];
     out[outOffset++] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
     out[outOffset++] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
     out[outOffset++] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
@@ -196,29 +200,29 @@
   /// starting at [matrixOffset]. Store result in [out] starting at [outOffset].
   static void transform4(Float32List out, int outOffset, Float32List matrix,
       int matrixOffset, Float32List vector, int vectorOffset) {
-    var x = vector[vectorOffset++];
-    var y = vector[vectorOffset++];
-    var z = vector[vectorOffset++];
-    var w = vector[vectorOffset++];
-    double m0 = matrix[matrixOffset];
-    double m4 = matrix[4 + matrixOffset];
-    double m8 = matrix[8 + matrixOffset];
-    double m12 = matrix[12 + matrixOffset];
+    final double x = vector[vectorOffset++];
+    final double y = vector[vectorOffset++];
+    final double z = vector[vectorOffset++];
+    final double w = vector[vectorOffset++];
+    final double m0 = matrix[matrixOffset];
+    final double m4 = matrix[4 + matrixOffset];
+    final double m8 = matrix[8 + matrixOffset];
+    final double m12 = matrix[12 + matrixOffset];
     out[outOffset++] = (m0 * x + m4 * y + m8 * z + m12 * w);
-    double m1 = matrix[1 + matrixOffset];
-    double m5 = matrix[5 + matrixOffset];
-    double m9 = matrix[9 + matrixOffset];
-    double m13 = matrix[13 + matrixOffset];
+    final double m1 = matrix[1 + matrixOffset];
+    final double m5 = matrix[5 + matrixOffset];
+    final double m9 = matrix[9 + matrixOffset];
+    final double m13 = matrix[13 + matrixOffset];
     out[outOffset++] = (m1 * x + m5 * y + m9 * z + m13 * w);
-    double m2 = matrix[2 + matrixOffset];
-    double m6 = matrix[6 + matrixOffset];
-    double m10 = matrix[10 + matrixOffset];
-    double m14 = matrix[14 + matrixOffset];
+    final double m2 = matrix[2 + matrixOffset];
+    final double m6 = matrix[6 + matrixOffset];
+    final double m10 = matrix[10 + matrixOffset];
+    final double m14 = matrix[14 + matrixOffset];
     out[outOffset++] = (m2 * x + m6 * y + m10 * z + m14 * w);
-    double m3 = matrix[3 + matrixOffset];
-    double m7 = matrix[7 + matrixOffset];
-    double m11 = matrix[11 + matrixOffset];
-    double m15 = matrix[15 + matrixOffset];
+    final double m3 = matrix[3 + matrixOffset];
+    final double m7 = matrix[7 + matrixOffset];
+    final double m11 = matrix[11 + matrixOffset];
+    final double m15 = matrix[15 + matrixOffset];
     out[outOffset++] = (m3 * x + m7 * y + m11 * z + m15 * w);
   }
 
@@ -262,26 +266,26 @@
   /// [out] = [A] * [B]; Starting at [outOffset], [aOffset], and [bOffset].
   static void multiply(Float32x4List out, int outOffset, Float32x4List A,
       int aOffset, Float32x4List B, int bOffset) {
-    var a0 = A[aOffset++];
-    var a1 = A[aOffset++];
-    var a2 = A[aOffset++];
-    var a3 = A[aOffset++];
-    var b0 = B[bOffset++];
+    final Float32x4 a0 = A[aOffset++];
+    final Float32x4 a1 = A[aOffset++];
+    final Float32x4 a2 = A[aOffset++];
+    final Float32x4 a3 = A[aOffset++];
+    final Float32x4 b0 = B[bOffset++];
     out[outOffset++] = b0.shuffle(Float32x4.XXXX) * a0 +
         b0.shuffle(Float32x4.YYYY) * a1 +
         b0.shuffle(Float32x4.ZZZZ) * a2 +
         b0.shuffle(Float32x4.WWWW) * a3;
-    var b1 = B[bOffset++];
+    final Float32x4 b1 = B[bOffset++];
     out[outOffset++] = b1.shuffle(Float32x4.XXXX) * a0 +
         b1.shuffle(Float32x4.YYYY) * a1 +
         b1.shuffle(Float32x4.ZZZZ) * a2 +
         b1.shuffle(Float32x4.WWWW) * a3;
-    var b2 = B[bOffset++];
+    final Float32x4 b2 = B[bOffset++];
     out[outOffset++] = b2.shuffle(Float32x4.XXXX) * a0 +
         b2.shuffle(Float32x4.YYYY) * a1 +
         b2.shuffle(Float32x4.ZZZZ) * a2 +
         b2.shuffle(Float32x4.WWWW) * a3;
-    var b3 = B[bOffset++];
+    final Float32x4 b3 = B[bOffset++];
     out[outOffset++] = b3.shuffle(Float32x4.XXXX) * a0 +
         b3.shuffle(Float32x4.YYYY) * a1 +
         b3.shuffle(Float32x4.ZZZZ) * a2 +
@@ -292,20 +296,20 @@
   /// starting at [matrixOffset]. Store result in [out] starting at [outOffset].
   static void transform4(Float32x4List out, int outOffset, Float32x4List matrix,
       int matrixOffset, Float32x4List vector, int vectorOffset) {
-    Float32x4 v = vector[vectorOffset];
-    Float32x4 xxxx = v.shuffle(Float32x4.XXXX);
+    final Float32x4 v = vector[vectorOffset];
+    final Float32x4 xxxx = v.shuffle(Float32x4.XXXX);
     Float32x4 z = new Float32x4.zero();
     z += xxxx * matrix[0 + matrixOffset];
-    Float32x4 yyyy = v.shuffle(Float32x4.YYYY);
+    final Float32x4 yyyy = v.shuffle(Float32x4.YYYY);
     z += yyyy * matrix[1 + matrixOffset];
-    Float32x4 zzzz = v.shuffle(Float32x4.ZZZZ);
+    final Float32x4 zzzz = v.shuffle(Float32x4.ZZZZ);
     z += zzzz * matrix[2 + matrixOffset];
     z += matrix[3 + matrixOffset];
     out[0 + outOffset] = z;
   }
 
   static void zero(Float32x4List matrix, int offset) {
-    var z = new Float32x4.zero();
+    final Float32x4 z = new Float32x4.zero();
     matrix[offset++] = z;
     matrix[offset++] = z;
     matrix[offset++] = z;
diff --git a/pub/vector_math/lib/vector_math.dart b/pub/vector_math/lib/vector_math.dart
index c7cfaa9..a9c1a32 100644
--- a/pub/vector_math/lib/vector_math.dart
+++ b/pub/vector_math/lib/vector_math.dart
@@ -19,8 +19,8 @@
 /// numbers for storage.
 library vector_math;
 
+import 'dart:math' as math;
 import 'dart:typed_data';
-import 'dart:math' as Math;
 import 'hash.dart' as quiver;
 
 part 'src/vector_math/utilities.dart';
diff --git a/pub/vector_math/lib/vector_math_64.dart b/pub/vector_math/lib/vector_math_64.dart
index 1ed52b1..16faa8f 100644
--- a/pub/vector_math/lib/vector_math_64.dart
+++ b/pub/vector_math/lib/vector_math_64.dart
@@ -19,8 +19,8 @@
 /// numbers for storage.
 library vector_math_64;
 
+import 'dart:math' as math;
 import 'dart:typed_data';
-import 'dart:math' as Math;
 import 'hash.dart' as quiver;
 
 part 'src/vector_math_64/utilities.dart';
diff --git a/pub/vector_math/lib/vector_math_geometry.dart b/pub/vector_math/lib/vector_math_geometry.dart
index 353bc29..6dc17e7 100644
--- a/pub/vector_math/lib/vector_math_geometry.dart
+++ b/pub/vector_math/lib/vector_math_geometry.dart
@@ -7,8 +7,8 @@
 /// [ColorFilter] and [InvertFilter]).
 library vector_math_geometry;
 
+import 'dart:math' as math;
 import 'dart:typed_data';
-import 'dart:math' as Math;
 
 import 'package:vector_math/vector_math.dart';
 import 'package:vector_math/vector_math_lists.dart';
diff --git a/pub/vector_math/lib/vector_math_lists.dart b/pub/vector_math/lib/vector_math_lists.dart
index 10d09af..0c19993 100644
--- a/pub/vector_math/lib/vector_math_lists.dart
+++ b/pub/vector_math/lib/vector_math_lists.dart
@@ -5,8 +5,8 @@
 /// A library for working with lists of vectors in a memory efficient way.
 library vector_math_lists;
 
+import 'dart:math' as math;
 import 'dart:typed_data';
-import 'dart:math' as Math;
 import 'package:vector_math/vector_math.dart';
 
 part 'src/vector_math_lists/scalar_list_view.dart';
diff --git a/pub/vector_math/pubspec.yaml b/pub/vector_math/pubspec.yaml
index c85ec11..6eab1e9 100644
--- a/pub/vector_math/pubspec.yaml
+++ b/pub/vector_math/pubspec.yaml
@@ -1,10 +1,10 @@
 name: vector_math
-version: 2.0.4
+version: 2.0.5
 author: John McCutchan <john@johnmccutchan.com>
 description: A Vector Math library for 2D and 3D applications.
 homepage: https://github.com/google/vector_math.dart
 environment:
-  sdk: '>=1.0.0 <2.0.0'
+  sdk: '>=1.21.0 <2.0.0'
 dev_dependencies:
   benchmark_harness: any
   browser: any
diff --git a/pub/vector_math/tool/generate_vector_math_64.dart b/pub/vector_math/tool/generate_vector_math_64.dart
index 6576ab8..56b63d8 100644
--- a/pub/vector_math/tool/generate_vector_math_64.dart
+++ b/pub/vector_math/tool/generate_vector_math_64.dart
@@ -8,28 +8,28 @@
 
 import 'package:path/path.dart' as p;
 
-main() async {
+Future<Null> main() async {
   await generateVectorMath64();
 
   print('Generated vector_math_64');
 }
 
-Future generateVectorMath64() async {
-  final directory = new Directory('lib/src/vector_math_64/');
-  final libraryFile = new File('lib/vector_math_64.dart');
+Future<Null> generateVectorMath64() async {
+  final Directory directory = new Directory('lib/src/vector_math_64/');
+  final File libraryFile = new File('lib/vector_math_64.dart');
 
   if (await directory.exists()) {
     await directory.delete(recursive: true);
   }
 
-  if (await libraryFile.exists()) {
+  if (libraryFile.existsSync()) {
     await libraryFile.delete();
   }
 
   await directory.create(recursive: true);
   await _processFile('lib/vector_math.dart');
 
-  await for (var f
+  await for (FileSystemEntity f
       in new Directory('lib/src/vector_math/').list(recursive: true)) {
     if (f is File) {
       await _processFile(f.path);
@@ -37,24 +37,22 @@
   }
 }
 
-Future _processFile(String inputFileName) async {
-  final inputFile = new File(inputFileName);
+Future<Null> _processFile(String inputFileName) async {
+  final File inputFile = new File(inputFileName);
 
-  final input = await inputFile.readAsString();
-  final output = _convertToVectorMath64(input);
+  final String input = await inputFile.readAsString();
+  final String output = _convertToVectorMath64(input);
 
-  final outputFileName =
+  final String outputFileName =
       inputFileName.replaceAll('vector_math', 'vector_math_64');
-  var dir = new Directory(p.dirname(outputFileName));
+  final Directory dir = new Directory(p.dirname(outputFileName));
 
   await dir.create(recursive: true);
 
-  final outputFile = new File(outputFileName);
+  final File outputFile = new File(outputFileName);
   await outputFile.writeAsString(output);
 }
 
-String _convertToVectorMath64(String input) {
-  return input
-      .replaceAll('vector_math', 'vector_math_64')
-      .replaceAll('Float32List', 'Float64List');
-}
+String _convertToVectorMath64(String input) => input
+    .replaceAll('vector_math', 'vector_math_64')
+    .replaceAll('Float32List', 'Float64List');