[roll] Update third-party dart packages

Updated:
Change-Id: If8bf2bc8d032b982afd7d2f60a4f9a7fde5a6e73
diff --git a/built_value/BUILD.gn b/built_value/BUILD.gn
index 6aa0abe..b928ca8 100644
--- a/built_value/BUILD.gn
+++ b/built_value/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for built_value-6.6.0
+# This file is generated by importer.py for built_value-6.7.0
 
 import("//build/dart/dart_library.gni")
 
diff --git a/built_value/CHANGELOG.md b/built_value/CHANGELOG.md
index 56109c9..ec1b90c 100644
--- a/built_value/CHANGELOG.md
+++ b/built_value/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+# 6.7.0
+
+- Generate code compatible with 'no raw types'.
+
 # 6.6.0
 
 - Allow providing your own `toString` via a mixin.
diff --git a/built_value/README.md b/built_value/README.md
index 0bf40f5..5238780 100644
--- a/built_value/README.md
+++ b/built_value/README.md
@@ -104,7 +104,7 @@
 snippets support in your favourite text editor. For example, in IntelliJ you
 can use following live template:
 
-```
+```dart
 abstract class $CLASS_NAME$ implements Built<$CLASS_NAME$, $CLASS_NAME$Builder> {
   $CLASS_NAME$._();
   factory $CLASS_NAME$([void Function($CLASS_NAME$Builder) updates]) = _$$$CLASS_NAME$;
@@ -188,12 +188,12 @@
 a common usage example is shown here. This example assumes that you are writing
 a client for a JSON API representing a person that looks like the following:
 
-```
+```json
 {
-  id: 12345,
-  age: 35,
-  first_name: 'Jimmy',
-  hobbies: ['jumping', 'basketball']
+  "id": 12345,
+  "age": 35,
+  "first_name": "Jimmy",
+  "hobbies": ["jumping", "basketball"]
 }
 ```
 
@@ -206,7 +206,7 @@
 annotation to map between the property name on the response and the name of the
 member variable in the `Person` class.
 
-```
+```dart
 import 'package:built_value/built_value.dart';
 import 'package:built_value/serializer.dart';
 import 'package:built_collection/built_collection.dart';
diff --git a/built_value/pubspec.yaml b/built_value/pubspec.yaml
index 5b19e01..5667d9e 100644
--- a/built_value/pubspec.yaml
+++ b/built_value/pubspec.yaml
@@ -1,5 +1,5 @@
 name: built_value
-version: 6.6.0
+version: 6.7.0
 description: >
   Value types with builders, Dart classes as enums, and serialization.
   This library is the runtime dependency.
diff --git a/connectivity/BUILD.gn b/connectivity/BUILD.gn
index cdd798a..c3ea74e 100644
--- a/connectivity/BUILD.gn
+++ b/connectivity/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for connectivity-0.4.3+2
+# This file is generated by importer.py for connectivity-0.4.3+4
 
 import("//build/dart/dart_library.gni")
 
diff --git a/connectivity/CHANGELOG.md b/connectivity/CHANGELOG.md
index 8e68043..4aa2f43 100644
--- a/connectivity/CHANGELOG.md
+++ b/connectivity/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.4.3+4
+
+* [Android] Updated logic to retrieve network info.
+
+## 0.4.3+3
+
+* Support for TYPE_MOBILE_HIPRI on Android.
+
 ## 0.4.3+2
 
 * Add missing template type parameter to `invokeMethod` calls.
diff --git a/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java b/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java
index ca2f522..830e701 100644
--- a/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java
+++ b/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java
@@ -70,6 +70,7 @@
         return "wifi";
       case ConnectivityManager.TYPE_MOBILE:
       case ConnectivityManager.TYPE_MOBILE_DUN:
+      case ConnectivityManager.TYPE_MOBILE_HIPRI:
         return "mobile";
       default:
         return "none";
@@ -98,11 +99,15 @@
   }
 
   private void handleCheck(MethodCall call, final Result result) {
+    result.success(checkNetworkType());
+  }
+
+  private String checkNetworkType() {
     NetworkInfo info = manager.getActiveNetworkInfo();
     if (info != null && info.isConnected()) {
-      result.success(getNetworkType(info.getType()));
+      return getNetworkType(info.getType());
     } else {
-      result.success("none");
+      return "none";
     }
   }
 
@@ -153,14 +158,7 @@
     return new BroadcastReceiver() {
       @Override
       public void onReceive(Context context, Intent intent) {
-        boolean isLost = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-        if (isLost) {
-          events.success("none");
-          return;
-        }
-
-        int type = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, -1);
-        events.success(getNetworkType(type));
+        events.success(checkNetworkType());
       }
     };
   }
diff --git a/connectivity/pubspec.yaml b/connectivity/pubspec.yaml
index 0f1f83b..788e1d0 100644
--- a/connectivity/pubspec.yaml
+++ b/connectivity/pubspec.yaml
@@ -3,7 +3,7 @@
   mobile/cellular) connectivity on Android and iOS.
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity
-version: 0.4.3+2
+version: 0.4.3+4
 
 flutter:
   plugin:
diff --git a/coverage/.github/no-response.yml b/coverage/.github/no-response.yml
new file mode 100644
index 0000000..d017e04
--- /dev/null
+++ b/coverage/.github/no-response.yml
@@ -0,0 +1,16 @@
+# Configuration for probot-no-response - https://github.com/probot/no-response
+
+# Number of days of inactivity before an Issue is closed for lack of response
+daysUntilClose: 21
+
+# Label requiring a response
+responseRequiredLabel: "awaiting response"
+
+# Comment to post when closing an Issue for lack of response. Set to `false` to disable
+closeComment: >-
+  Without additional information, we are unfortunately not sure how to resolve
+  this issue. We are therefore reluctantly going to close this issue for now.
+  Please don't hesitate to comment on the issue if you have any more
+  information for us; we will reopen it right away!
+  
+  Thanks for your contribution.
diff --git a/coverage/.travis.yml b/coverage/.travis.yml
index fecc637..b8b72a4 100644
--- a/coverage/.travis.yml
+++ b/coverage/.travis.yml
@@ -1,10 +1,24 @@
 language: dart
+
 dart:
-  - stable
+  - 2.0.0
+  - dev
+
 install:
   - gem install coveralls-lcov
+
 script: ./tool/travis.sh
+
 after_success:
   - coveralls-lcov var/lcov.info
+
 env:
   - DARTANALYZER_FLAGS=--fatal-warnings
+
+# 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/coverage/BUILD.gn b/coverage/BUILD.gn
index 90fc26d..4768b2a 100644
--- a/coverage/BUILD.gn
+++ b/coverage/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for coverage-0.12.4
+# This file is generated by importer.py for coverage-0.13.0
 
 import("//build/dart/dart_library.gni")
 
@@ -15,8 +15,8 @@
     "//third_party/dart-pkg/pub/stack_trace",
     "//third_party/dart-pkg/pub/package_config",
     "//third_party/dart-pkg/pub/logging",
-    "//third_party/dart-pkg/pub/vm_service_client",
     "//third_party/dart-pkg/pub/path",
+    "//third_party/dart-pkg/pub/vm_service_lib",
     "//third_party/dart-pkg/pub/args",
   ]
 }
diff --git a/coverage/CHANGELOG.md b/coverage/CHANGELOG.md
index 3f1efec..ae85ed4 100644
--- a/coverage/CHANGELOG.md
+++ b/coverage/CHANGELOG.md
@@ -1,8 +1,21 @@
+## 0.13.0 - 2019-07-10
+
+ * BREAKING CHANGE: Skips collecting coverage for `dart:` libaries by default,
+   which provides a significant performance boost. To restore the previous
+   behaviour and collect coverage for these libraries, use the `--include-dart`
+   flag.
+ * Disables WebSocket compression for coverage collection. Since almost all
+   coverage collection runs happen over the loopback interface to localhost,
+   this improves performance and reduces CPU usage.
+ * Migrates implementation of VM service protocol library from
+   `package:vm_service_client`, which is no longer maintained, to
+   `package:vm_service_lib`, which is.
+
 ## 0.12.4 - 2019-01-11
 
  * `collect()` now immediately throws `ArgumentError` if a null URI is passed
-    in the `serviceUri` parameter to avoid a less-easily debuggable null
-    dereference later. See dart-lang/coverage#240 for details.
+   in the `serviceUri` parameter to avoid a less-easily debuggable null
+   dereference later. See dart-lang/coverage#240 for details.
 
 ## 0.12.3 - 2018-10-19
 
diff --git a/coverage/analysis_options.yaml b/coverage/analysis_options.yaml
index 9cc7184..5960f55 100644
--- a/coverage/analysis_options.yaml
+++ b/coverage/analysis_options.yaml
@@ -13,8 +13,6 @@
   errors:
     # treat missing required parameters as a warning (not a hint)
     missing_required_param: warning
-    # allow overriding fields (if they use super, ideally...)
-    strong_mode_invalid_field_override: ignore
     # allow type narrowing
     strong_mode_down_cast_composite: ignore
     # allow having TODOs in the code
@@ -54,7 +52,6 @@
     - await_only_futures
     - camel_case_types
     - constant_identifier_names
-    - control_flow_in_finally
     - empty_constructor_bodies
     - implementation_imports
     - library_names
@@ -65,17 +62,20 @@
     - overridden_fields
     - package_api_docs
     - package_prefixed_library_names
-    # - prefer_final_locals
+    - prefer_equal_for_default_values
+    - prefer_final_locals
+    - prefer_generic_function_type_aliases
     - prefer_is_not_empty
     # - public_member_api_docs
     - slash_for_doc_comments
     - sort_constructors_first
     - sort_unnamed_constructors_first
-    - super_goes_last
     - type_annotate_public_apis # subset of always_specify_types
     - type_init_formals
     - unnecessary_brace_in_string_interps
+    - unnecessary_const
     - unnecessary_getters_setters
+    - unnecessary_new
 
     # === pub rules ===
     - package_names
diff --git a/coverage/bin/collect_coverage.dart b/coverage/bin/collect_coverage.dart
index ddb1ce3..dccb996 100644
--- a/coverage/bin/collect_coverage.dart
+++ b/coverage/bin/collect_coverage.dart
@@ -17,10 +17,10 @@
     print('${rec.level.name}: ${rec.time}: ${rec.message}');
   });
 
-  var options = _parseArgs(arguments);
+  final options = _parseArgs(arguments);
   await Chain.capture(() async {
-    var coverage = await collect(
-        options.serviceUri, options.resume, options.waitPaused,
+    final coverage = await collect(options.serviceUri, options.resume,
+        options.waitPaused, options.includeDart,
         timeout: options.timeout);
     options.out.write(json.encode(coverage));
     await options.out.close();
@@ -34,18 +34,19 @@
 }
 
 class Options {
-  Options(
-      this.serviceUri, this.out, this.timeout, this.waitPaused, this.resume);
+  Options(this.serviceUri, this.out, this.timeout, this.waitPaused, this.resume,
+      this.includeDart);
 
   final Uri serviceUri;
   final IOSink out;
   final Duration timeout;
   final bool waitPaused;
   final bool resume;
+  final bool includeDart;
 }
 
 Options _parseArgs(List<String> arguments) {
-  var parser = new ArgParser()
+  final parser = ArgParser()
     ..addOption('host',
         abbr: 'H',
         help: 'remote VM host. DEPRECATED: use --uri',
@@ -65,9 +66,11 @@
         help: 'wait for all isolates to be paused before collecting coverage')
     ..addFlag('resume-isolates',
         abbr: 'r', defaultsTo: false, help: 'resume all isolates on exit')
+    ..addFlag('include-dart',
+        abbr: 'd', defaultsTo: false, help: 'include "dart:" libraries')
     ..addFlag('help', abbr: 'h', negatable: false, help: 'show this help');
 
-  var args = parser.parse(arguments);
+  final args = parser.parse(arguments);
 
   void printUsage() {
     print('Usage: dart collect_coverage.dart --uri=http://... [OPTION...]\n');
@@ -102,12 +105,12 @@
   if (args['out'] == 'stdout') {
     out = stdout;
   } else {
-    var outfile = new File(args['out'])..createSync(recursive: true);
+    final outfile = File(args['out'])..createSync(recursive: true);
     out = outfile.openWrite();
   }
-  var timeout = (args['connect-timeout'] == null)
+  final timeout = (args['connect-timeout'] == null)
       ? null
-      : new Duration(seconds: int.parse(args['connect-timeout']));
-  return new Options(
-      serviceUri, out, timeout, args['wait-paused'], args['resume-isolates']);
+      : Duration(seconds: int.parse(args['connect-timeout']));
+  return Options(serviceUri, out, timeout, args['wait-paused'],
+      args['resume-isolates'], args['include-dart']);
 }
diff --git a/coverage/bin/format_coverage.dart b/coverage/bin/format_coverage.dart
index 4e65129..259e1c7 100644
--- a/coverage/bin/format_coverage.dart
+++ b/coverage/bin/format_coverage.dart
@@ -30,7 +30,7 @@
 Future<Null> main(List<String> arguments) async {
   final env = parseArgs(arguments);
 
-  List<File> files = filesToProcess(env.input);
+  final List<File> files = filesToProcess(env.input);
   if (env.verbose) {
     print('Environment:');
     print('  # files: ${files.length}');
@@ -41,8 +41,8 @@
     print('  report-on: ${env.reportOn}');
   }
 
-  var clock = new Stopwatch()..start();
-  var hitmap = await parseCoverage(files, env.workers);
+  final clock = Stopwatch()..start();
+  final hitmap = await parseCoverage(files, env.workers);
 
   // All workers are done. Process the data.
   if (env.verbose) {
@@ -50,20 +50,20 @@
   }
 
   String output;
-  var resolver = env.bazel
-      ? new BazelResolver(workspacePath: env.bazelWorkspace)
-      : new Resolver(
+  final resolver = env.bazel
+      ? BazelResolver(workspacePath: env.bazelWorkspace)
+      : Resolver(
           packagesPath: env.packagesPath,
           packageRoot: env.pkgRoot,
           sdkRoot: env.sdkRoot);
-  var loader = new Loader();
+  final loader = Loader();
   if (env.prettyPrint) {
     output =
-        await new PrettyPrintFormatter(resolver, loader, reportOn: env.reportOn)
+        await PrettyPrintFormatter(resolver, loader, reportOn: env.reportOn)
             .format(hitmap);
   } else {
     assert(env.lcov);
-    output = await new LcovFormatter(resolver,
+    output = await LcovFormatter(resolver,
             reportOn: env.reportOn, basePath: env.baseDirectory)
         .format(hitmap);
   }
@@ -94,8 +94,8 @@
 /// Checks the validity of the provided arguments. Does not initialize actual
 /// processing.
 Environment parseArgs(List<String> arguments) {
-  final env = new Environment();
-  var parser = new ArgParser();
+  final env = Environment();
+  final parser = ArgParser();
 
   parser.addOption('sdk-root', abbr: 's', help: 'path to the SDK root');
   parser.addOption('package-root', abbr: 'p', help: 'path to the package root');
@@ -126,7 +126,7 @@
       abbr: 'v', negatable: false, help: 'verbose output');
   parser.addFlag('help', abbr: 'h', negatable: false, help: 'show this help');
 
-  var args = parser.parse(arguments);
+  final args = parser.parse(arguments);
 
   void printUsage() {
     print('Usage: dart format_coverage.dart [OPTION...]\n');
@@ -182,8 +182,8 @@
   if (args['out'] == 'stdout') {
     env.output = stdout;
   } else {
-    var outpath = p.absolute(p.normalize(args['out']));
-    var outfile = new File(outpath)..createSync(recursive: true);
+    final outpath = p.absolute(p.normalize(args['out']));
+    final outfile = File(outpath)..createSync(recursive: true);
     env.output = outfile.openWrite();
   }
 
@@ -220,13 +220,13 @@
 /// are contained by it if it is a directory, or a [List] containing the file if
 /// it is a file.
 List<File> filesToProcess(String absPath) {
-  var filePattern = new RegExp(r'^dart-cov-\d+-\d+.json$');
+  final filePattern = RegExp(r'^dart-cov-\d+-\d+.json$');
   if (FileSystemEntity.isDirectorySync(absPath)) {
-    return new Directory(absPath)
+    return Directory(absPath)
         .listSync(recursive: true)
         .whereType<File>()
         .where((e) => filePattern.hasMatch(p.basename(e.path)))
         .toList();
   }
-  return <File>[new File(absPath)];
+  return <File>[File(absPath)];
 }
diff --git a/coverage/bin/run_and_collect.dart b/coverage/bin/run_and_collect.dart
index 9cbba0d..ead8792 100644
--- a/coverage/bin/run_and_collect.dart
+++ b/coverage/bin/run_and_collect.dart
@@ -7,6 +7,6 @@
 import 'package:coverage/src/run_and_collect.dart';
 
 Future<Null> main(List<String> args) async {
-  Map results = await runAndCollect(args[0], packageRoot: args[1]);
+  final Map results = await runAndCollect(args[0], packageRoot: args[1]);
   print(results);
 }
diff --git a/coverage/codereview.settings b/coverage/codereview.settings
deleted file mode 100644
index 4b0ed74..0000000
--- a/coverage/codereview.settings
+++ /dev/null
@@ -1,4 +0,0 @@
-# This file is used by gcl to get repository specific information.
-CODE_REVIEW_SERVER: http://codereview.chromium.org/
-VIEW_VC: https://github.com/dart-lang/coverage/commit/
-CC_LIST: reviews@dartlang.org
diff --git a/coverage/lib/src/collect.dart b/coverage/lib/src/collect.dart
index c85031d..cc8ec42 100644
--- a/coverage/lib/src/collect.dart
+++ b/coverage/lib/src/collect.dart
@@ -3,11 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io';
 
-import 'package:vm_service_client/vm_service_client.dart';
+import 'package:vm_service_lib/vm_service_lib.dart';
 import 'util.dart';
 
-const _retryInterval = const Duration(milliseconds: 200);
+const _retryInterval = Duration(milliseconds: 200);
 
 /// Collects coverage for all isolates in the running VM.
 ///
@@ -24,104 +25,163 @@
 /// If [waitPaused] is true, collection will not begin until all isolates are
 /// in the paused state.
 Future<Map<String, dynamic>> collect(
-    Uri serviceUri, bool resume, bool waitPaused,
+    Uri serviceUri, bool resume, bool waitPaused, bool includeDart,
     {Duration timeout}) async {
   if (serviceUri == null) throw ArgumentError('serviceUri must not be null');
 
   // Create websocket URI. Handle any trailing slashes.
-  var pathSegments = serviceUri.pathSegments.where((c) => c.isNotEmpty).toList()
-    ..add('ws');
-  var uri = serviceUri.replace(scheme: 'ws', pathSegments: pathSegments);
+  final pathSegments =
+      serviceUri.pathSegments.where((c) => c.isNotEmpty).toList()..add('ws');
+  final uri = serviceUri.replace(scheme: 'ws', pathSegments: pathSegments);
 
-  VMServiceClient vmService;
+  VmService service;
   await retry(() async {
     try {
-      vmService = new VMServiceClient.connect(uri);
-      await vmService.getVM().timeout(_retryInterval);
+      final options = const CompressionOptions(enabled: false);
+      final socket = await WebSocket.connect('$uri', compression: options);
+      final controller = StreamController<String>();
+      socket.listen((dynamic data) => controller.add(data));
+      service = VmService(
+          controller.stream, (String message) => socket.add(message),
+          log: StdoutLog(), disposeHandler: () => socket.close());
+      await service.getVM().timeout(_retryInterval);
     } on TimeoutException {
-      vmService.close();
+      service.dispose();
       rethrow;
     }
   }, _retryInterval, timeout: timeout);
   try {
     if (waitPaused) {
-      await _waitIsolatesPaused(vmService, timeout: timeout);
+      await _waitIsolatesPaused(service, timeout: timeout);
     }
 
-    return await _getAllCoverage(vmService);
+    return await _getAllCoverage(service, includeDart);
   } finally {
     if (resume) {
-      await _resumeIsolates(vmService);
+      await _resumeIsolates(service);
     }
-    await vmService.close();
+    service.dispose();
   }
 }
 
-Future<Map<String, dynamic>> _getAllCoverage(VMServiceClient service) async {
-  var vm = await service.getVM();
-  var allCoverage = <Map<String, dynamic>>[];
+Future<Map<String, dynamic>> _getAllCoverage(
+    VmService service, bool includeDart) async {
+  final vm = await service.getVM();
+  final allCoverage = <Map<String, dynamic>>[];
 
   for (var isolateRef in vm.isolates) {
-    var isolate = await isolateRef.load();
-    var report = await isolate.getSourceReport(forceCompile: true);
-    var coverage = await _getCoverageJson(service, report);
+    final SourceReport report = await service.getSourceReport(
+      isolateRef.id,
+      <String>[SourceReportKind.kCoverage],
+      forceCompile: true,
+    );
+    final coverage =
+        await _getCoverageJson(service, isolateRef, report, includeDart);
     allCoverage.addAll(coverage);
   }
   return <String, dynamic>{'type': 'CodeCoverage', 'coverage': allCoverage};
 }
 
-Future _resumeIsolates(VMServiceClient service) async {
-  var vm = await service.getVM();
+Future _resumeIsolates(VmService service) async {
+  final vm = await service.getVM();
   for (var isolateRef in vm.isolates) {
-    var isolate = await isolateRef.load();
-    if (isolate.isPaused) {
-      await isolateRef.resume();
+    final Isolate isolate = await service.getIsolate(isolateRef.id);
+    if (isolate.pauseEvent.kind != EventKind.kResume) {
+      await service.resume(isolateRef.id);
     }
   }
 }
 
-Future _waitIsolatesPaused(VMServiceClient service, {Duration timeout}) async {
+Future _waitIsolatesPaused(VmService service, {Duration timeout}) async {
+  final pauseEvents = Set<String>.from(<String>[
+    EventKind.kPauseStart,
+    EventKind.kPauseException,
+    EventKind.kPauseExit,
+    EventKind.kPauseInterrupted,
+    EventKind.kPauseBreakpoint
+  ]);
+
   Future allPaused() async {
-    var vm = await service.getVM();
+    final VM vm = await service.getVM();
     for (var isolateRef in vm.isolates) {
-      var isolate = await isolateRef.load();
-      if (!isolate.isPaused) throw "Unpaused isolates remaining.";
+      final Isolate isolate = await service.getIsolate(isolateRef.id);
+      if (!pauseEvents.contains(isolate.pauseEvent.kind)) {
+        throw "Unpaused isolates remaining.";
+      }
     }
   }
 
   return retry(allPaused, _retryInterval, timeout: timeout);
 }
 
-/// Returns a JSON coverage list backward-compatible with pre-1.16.0 SDKs.
-Future<List<Map<String, dynamic>>> _getCoverageJson(
-    VMServiceClient service, VMSourceReport report) async {
-  var scriptRefs = report.ranges.map((r) => r.script).toSet();
-  var scripts = <VMScriptRef, VMScript>{};
-  for (var ref in scriptRefs) {
-    scripts[ref] = await ref.load();
+/// Returns the line number to which the specified token position maps.
+///
+/// Performs a binary search within the script's token position table to locate
+/// the line in question.
+int _getLineFromTokenPos(Script script, int tokenPos) {
+  // TODO(cbracken): investigate whether caching this lookup results in
+  // significant performance gains.
+  var min = 0;
+  var max = script.tokenPosTable.length;
+  while (min < max) {
+    final mid = min + ((max - min) >> 1);
+    final row = script.tokenPosTable[mid];
+    if (row[1] > tokenPos) {
+      max = mid;
+    } else {
+      for (var i = 1; i < row.length; i += 2) {
+        if (row[i] == tokenPos) return row.first;
+      }
+      min = mid + 1;
+    }
   }
+  return null;
+}
 
+/// Returns a JSON coverage list backward-compatible with pre-1.16.0 SDKs.
+Future<List<Map<String, dynamic>>> _getCoverageJson(VmService service,
+    IsolateRef isolateRef, SourceReport report, bool includeDart) async {
   // script uri -> { line -> hit count }
-  var hitMaps = <Uri, Map<int, int>>{};
+  final hitMaps = <Uri, Map<int, int>>{};
+  final scripts = <ScriptRef, Script>{};
   for (var range in report.ranges) {
-    // Not returned in scripts section of source report.
-    if (range.script.uri.scheme == 'evaluate') continue;
+    final scriptRef = report.scripts[range.scriptIndex];
+    final Uri scriptUri = Uri.parse(report.scripts[range.scriptIndex].uri);
 
-    hitMaps.putIfAbsent(range.script.uri, () => <int, int>{});
-    var hitMap = hitMaps[range.script.uri];
-    var script = scripts[range.script];
-    for (VMScriptToken hit in range.hits ?? []) {
-      var line = script.sourceLocation(hit).line + 1;
+    // Not returned in scripts section of source report.
+    if (scriptUri.scheme == 'evaluate') continue;
+
+    // Skip scripts from dart:.
+    if (!includeDart && scriptUri.scheme == 'dart') continue;
+
+    if (!scripts.containsKey(scriptRef)) {
+      scripts[scriptRef] = await service.getObject(isolateRef.id, scriptRef.id);
+    }
+    final script = scripts[scriptRef];
+
+    // Look up the hit map for this script (shared across isolates).
+    final hitMap = hitMaps.putIfAbsent(scriptUri, () => <int, int>{});
+
+    // Collect hits and misses.
+    final coverage = range.coverage;
+    for (final tokenPos in coverage.hits) {
+      final line = _getLineFromTokenPos(script, tokenPos);
+      if (line == null) {
+        print('tokenPos $tokenPos has no line mapping for script $scriptUri');
+      }
       hitMap[line] = hitMap.containsKey(line) ? hitMap[line] + 1 : 1;
     }
-    for (VMScriptToken miss in range.misses ?? []) {
-      var line = script.sourceLocation(miss).line + 1;
+    for (final tokenPos in coverage.misses) {
+      final line = _getLineFromTokenPos(script, tokenPos);
+      if (line == null) {
+        print('tokenPos $tokenPos has no line mapping for script $scriptUri');
+      }
       hitMap.putIfAbsent(line, () => 0);
     }
   }
 
   // Output JSON
-  var coverage = <Map<String, dynamic>>[];
+  final coverage = <Map<String, dynamic>>[];
   hitMaps.forEach((uri, hitMap) {
     coverage.add(_toScriptCoverageJson(uri, hitMap));
   });
@@ -131,8 +191,8 @@
 /// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs.
 Map<String, dynamic> _toScriptCoverageJson(
     Uri scriptUri, Map<int, int> hitMap) {
-  var json = <String, dynamic>{};
-  var hits = <int>[];
+  final json = <String, dynamic>{};
+  final hits = <int>[];
   hitMap.forEach((line, hitCount) {
     hits.add(line);
     hits.add(hitCount);
@@ -148,3 +208,10 @@
   json['hits'] = hits;
   return json;
 }
+
+class StdoutLog extends Log {
+  @override
+  void warning(String message) => print(message);
+  @override
+  void severe(String message) => print(message);
+}
diff --git a/coverage/lib/src/formatter.dart b/coverage/lib/src/formatter.dart
index 1c4f7c2..1d8383e 100644
--- a/coverage/lib/src/formatter.dart
+++ b/coverage/lib/src/formatter.dart
@@ -19,7 +19,7 @@
 /// Returns a [Future] that completes as soon as all map entries have been
 /// emitted.
 class LcovFormatter implements Formatter {
-  /// Creates a new LCOV formatter.
+  /// Creates a LCOV formatter.
   ///
   /// If [reportOn] is provided, coverage report output is limited to files
   /// prefixed with one of the paths included. If [basePath] is provided, paths
@@ -32,10 +32,10 @@
 
   @override
   Future<String> format(Map hitmap) async {
-    _PathFilter pathFilter = _getPathFilter(reportOn);
-    var buf = new StringBuffer();
+    final _PathFilter pathFilter = _getPathFilter(reportOn);
+    final buf = StringBuffer();
     for (var key in hitmap.keys) {
-      Map<int, int> v = hitmap[key];
+      final Map<int, int> v = hitmap[key];
       var source = resolver.resolve(key);
       if (source == null) {
         continue;
@@ -69,7 +69,7 @@
 /// Returns a [Future] that completes as soon as all map entries have been
 /// emitted.
 class PrettyPrintFormatter implements Formatter {
-  /// Creates a new pretty-print formatter.
+  /// Creates a pretty-print formatter.
   ///
   /// If [reportOn] is provided, coverage report output is limited to files
   /// prefixed with one of the paths included.
@@ -81,11 +81,11 @@
 
   @override
   Future<String> format(Map hitmap) async {
-    _PathFilter pathFilter = _getPathFilter(reportOn);
-    var buf = new StringBuffer();
+    final _PathFilter pathFilter = _getPathFilter(reportOn);
+    final buf = StringBuffer();
     for (var key in hitmap.keys) {
-      Map<int, int> v = hitmap[key];
-      var source = resolver.resolve(key);
+      final Map<int, int> v = hitmap[key];
+      final source = resolver.resolve(key);
       if (source == null) {
         continue;
       }
@@ -94,7 +94,7 @@
         continue;
       }
 
-      var lines = await loader.load(source);
+      final lines = await loader.load(source);
       if (lines == null) {
         continue;
       }
@@ -114,11 +114,11 @@
 
 const _prefix = '       ';
 
-typedef bool _PathFilter(String path);
+typedef _PathFilter = bool Function(String path);
 
 _PathFilter _getPathFilter(List<String> reportOn) {
   if (reportOn == null) return (String path) => true;
 
-  var absolutePaths = reportOn.map(p.absolute).toList();
+  final absolutePaths = reportOn.map(p.absolute).toList();
   return (String path) => absolutePaths.any((item) => path.startsWith(item));
 }
diff --git a/coverage/lib/src/hitmap.dart b/coverage/lib/src/hitmap.dart
index da7c5ee..ab6fb69 100644
--- a/coverage/lib/src/hitmap.dart
+++ b/coverage/lib/src/hitmap.dart
@@ -12,37 +12,37 @@
 /// `jsonResult` is expected to be a List<Map<String, dynamic>>.
 Map<String, Map<int, int>> createHitmap(List jsonResult) {
   // Map of source file to map of line to hit count for that line.
-  var globalHitMap = <String, Map<int, int>>{};
+  final globalHitMap = <String, Map<int, int>>{};
 
   void addToMap(Map<int, int> map, int line, int count) {
-    var oldCount = map.putIfAbsent(line, () => 0);
+    final oldCount = map.putIfAbsent(line, () => 0);
     map[line] = count + oldCount;
   }
 
   for (Map<String, dynamic> e in jsonResult) {
-    String source = e['source'];
+    final String source = e['source'];
     if (source == null) {
       // Couldn't resolve import, so skip this entry.
       continue;
     }
 
-    var sourceHitMap = globalHitMap.putIfAbsent(source, () => <int, int>{});
-    List<dynamic> hits = e['hits'];
+    final sourceHitMap = globalHitMap.putIfAbsent(source, () => <int, int>{});
+    final List<dynamic> hits = e['hits'];
     // hits is a flat array of the following format:
     // [ <line|linerange>, <hitcount>,...]
     // line: number.
     // linerange: '<line>-<line>'.
     for (var i = 0; i < hits.length; i += 2) {
-      dynamic k = hits[i];
+      final dynamic k = hits[i];
       if (k is num) {
         // Single line.
         addToMap(sourceHitMap, k, hits[i + 1]);
       } else {
         assert(k is String);
         // Linerange. We expand line ranges to actual lines at this point.
-        int splitPos = k.indexOf('-');
-        int start = int.parse(k.substring(0, splitPos));
-        int end = int.parse(k.substring(splitPos + 1));
+        final int splitPos = k.indexOf('-');
+        final start = int.parse(k.substring(0, splitPos));
+        final end = int.parse(k.substring(splitPos + 1));
         for (var j = start; j <= end; j++) {
           addToMap(sourceHitMap, j, hits[i + 1]);
         }
@@ -72,10 +72,10 @@
 
 /// Generates a merged hitmap from a set of coverage JSON files.
 Future<Map> parseCoverage(Iterable<File> files, int _) async {
-  var globalHitmap = <String, Map<int, int>>{};
+  final globalHitmap = <String, Map<int, int>>{};
   for (var file in files) {
-    String contents = file.readAsStringSync();
-    List jsonResult = json.decode(contents)['coverage'];
+    final contents = file.readAsStringSync();
+    final List jsonResult = json.decode(contents)['coverage'];
     mergeHitmaps(createHitmap(jsonResult), globalHitmap);
   }
   return globalHitmap;
diff --git a/coverage/lib/src/resolver.dart b/coverage/lib/src/resolver.dart
index 472d41f..cff28b5 100644
--- a/coverage/lib/src/resolver.dart
+++ b/coverage/lib/src/resolver.dart
@@ -23,7 +23,7 @@
   /// Returns the absolute path wrt. to the given environment or null, if the
   /// import could not be resolved.
   String resolve(String scriptUri) {
-    var uri = Uri.parse(scriptUri);
+    final uri = Uri.parse(scriptUri);
     if (uri.scheme == 'dart') {
       if (sdkRoot == null) {
         // No sdk-root given, do not resolve dart: URIs.
@@ -40,11 +40,12 @@
         }
         // Canonicalize path. For instance: _collection-dev => _collection_dev.
         path = path.replaceAll('-', '_');
-        var pathSegments = [sdkRoot, path]..addAll(uri.pathSegments.sublist(1));
+        final pathSegments = [sdkRoot, path]
+          ..addAll(uri.pathSegments.sublist(1));
         filePath = p.joinAll(pathSegments);
       } else {
         // Resolve 'dart:something' to be something/something.dart in the SDK.
-        var lib = uri.path;
+        final lib = uri.path;
         filePath = p.join(sdkRoot, lib, '$lib.dart');
       }
       return resolveSymbolicLinks(filePath);
@@ -55,15 +56,15 @@
         return null;
       }
 
-      var packageName = uri.pathSegments[0];
+      final packageName = uri.pathSegments[0];
       if (_packages != null) {
-        var packageUri = _packages[packageName];
+        final packageUri = _packages[packageName];
         if (packageUri == null) {
           failed.add('$uri');
           return null;
         }
-        var packagePath = p.fromUri(packageUri);
-        var pathInPackage = p.joinAll(uri.pathSegments.sublist(1));
+        final packagePath = p.fromUri(packageUri);
+        final pathInPackage = p.joinAll(uri.pathSegments.sublist(1));
         return resolveSymbolicLinks(p.join(packagePath, pathInPackage));
       }
       return resolveSymbolicLinks(p.join(packageRoot, uri.path));
@@ -78,22 +79,22 @@
 
   /// Returns a canonicalized path, or `null` if the path cannot be resolved.
   String resolveSymbolicLinks(String path) {
-    var normalizedPath = p.normalize(path);
-    var type = FileSystemEntity.typeSync(normalizedPath, followLinks: true);
+    final normalizedPath = p.normalize(path);
+    final type = FileSystemEntity.typeSync(normalizedPath, followLinks: true);
     if (type == FileSystemEntityType.notFound) return null;
-    return new File(normalizedPath).resolveSymbolicLinksSync();
+    return File(normalizedPath).resolveSymbolicLinksSync();
   }
 
   static Map<String, Uri> _parsePackages(String packagesPath) {
-    var source = new File(packagesPath).readAsBytesSync();
-    return packages_file.parse(source, new Uri.file(packagesPath));
+    final source = File(packagesPath).readAsBytesSync();
+    return packages_file.parse(source, Uri.file(packagesPath));
   }
 }
 
 /// Bazel URI resolver.
 class BazelResolver extends Resolver {
   /// Creates a Bazel resolver with the specified workspace path, if any.
-  BazelResolver({this.workspacePath: ''});
+  BazelResolver({this.workspacePath = ''});
 
   final String workspacePath;
 
@@ -101,7 +102,7 @@
   /// import could not be resolved.
   @override
   String resolve(String scriptUri) {
-    var uri = Uri.parse(scriptUri);
+    final uri = Uri.parse(scriptUri);
     if (uri.scheme == 'dart') {
       // Ignore the SDK
       return null;
@@ -111,12 +112,11 @@
       return _resolveBazelPackage(uri.pathSegments);
     }
     if (uri.scheme == 'file') {
-      var runfilesPathSegment = '.runfiles/$workspacePath';
-      runfilesPathSegment =
-          runfilesPathSegment.replaceAll(new RegExp(r'/*$'), '/');
-      var runfilesPos = uri.path.indexOf(runfilesPathSegment);
+      final runfilesPathSegment =
+          '.runfiles/$workspacePath'.replaceAll(RegExp(r'/*$'), '/');
+      final runfilesPos = uri.path.indexOf(runfilesPathSegment);
       if (runfilesPos >= 0) {
-        int pathStart = runfilesPos + runfilesPathSegment.length;
+        final pathStart = runfilesPos + runfilesPathSegment.length;
         return uri.path.substring(pathStart);
       }
       return null;
@@ -130,9 +130,9 @@
   }
 
   String _extractHttpPath(Uri uri) {
-    int packagesPos = uri.pathSegments.indexOf('packages');
+    final packagesPos = uri.pathSegments.indexOf('packages');
     if (packagesPos >= 0) {
-      var workspacePath = uri.pathSegments.sublist(packagesPos + 1);
+      final workspacePath = uri.pathSegments.sublist(packagesPos + 1);
       return _resolveBazelPackage(workspacePath);
     }
     return uri.pathSegments.join('/');
@@ -140,14 +140,11 @@
 
   String _resolveBazelPackage(List<String> pathSegments) {
     // TODO(cbracken) belongs in a Bazel package
-    var packageName = pathSegments[0];
-    var pathInPackage = pathSegments.sublist(1).join('/');
-    String packagePath;
-    if (packageName.contains('.')) {
-      packagePath = packageName.replaceAll('.', '/');
-    } else {
-      packagePath = 'third_party/dart/$packageName';
-    }
+    final packageName = pathSegments[0];
+    final pathInPackage = pathSegments.sublist(1).join('/');
+    final packagePath = packageName.contains('.')
+        ? packageName.replaceAll('.', '/')
+        : 'third_party/dart/$packageName';
     return '$packagePath/lib/$pathInPackage';
   }
 }
@@ -160,7 +157,7 @@
   /// Returns `null` if the resource could not be loaded.
   Future<List<String>> load(String path) async {
     try {
-      return new File(path).readAsLines();
+      return File(path).readAsLines();
     } catch (_) {
       failed.add(path);
       return null;
diff --git a/coverage/lib/src/run_and_collect.dart b/coverage/lib/src/run_and_collect.dart
index d12d130..448009b 100644
--- a/coverage/lib/src/run_and_collect.dart
+++ b/coverage/lib/src/run_and_collect.dart
@@ -11,10 +11,11 @@
 
 Future<Map<String, dynamic>> runAndCollect(String scriptPath,
     {List<String> scriptArgs,
-    bool checked: false,
+    bool checked = false,
     String packageRoot,
+    bool includeDart = false,
     Duration timeout}) async {
-  var dartArgs = [
+  final dartArgs = [
     '--enable-vm-service',
     '--pause_isolates_on_exit',
   ];
@@ -33,26 +34,27 @@
     dartArgs.addAll(scriptArgs);
   }
 
-  var process = await Process.start('dart', dartArgs);
-  var serviceUriCompleter = new Completer<Uri>();
+  final process = await Process.start('dart', dartArgs);
+  final serviceUriCompleter = Completer<Uri>();
   process.stdout
       .transform(utf8.decoder)
       .transform(const LineSplitter())
       .listen((line) {
-    var uri = extractObservatoryUri(line);
+    final uri = extractObservatoryUri(line);
     if (uri != null) {
       serviceUriCompleter.complete(uri);
     }
   });
 
-  var serviceUri = await serviceUriCompleter.future;
+  final serviceUri = await serviceUriCompleter.future;
   Map<String, dynamic> coverage;
   try {
-    coverage = await collect(serviceUri, true, true, timeout: timeout);
+    coverage =
+        await collect(serviceUri, true, true, includeDart, timeout: timeout);
   } finally {
     await process.stderr.drain<List<int>>();
   }
-  int exitStatus = await process.exitCode;
+  final exitStatus = await process.exitCode;
   if (exitStatus != 0) {
     throw "Process exited with exit code $exitStatus";
   }
diff --git a/coverage/lib/src/util.dart b/coverage/lib/src/util.dart
index 071d991..8f8ed15 100644
--- a/coverage/lib/src/util.dart
+++ b/coverage/lib/src/util.dart
@@ -18,10 +18,10 @@
 
     return f().timeout(duration, onTimeout: () {
       keepGoing = false;
-      var msg = duration.inSeconds == 0
+      final msg = duration.inSeconds == 0
           ? '${duration.inMilliseconds}ms'
           : '${duration.inSeconds}s';
-      throw new StateError('Failed to complete within $msg');
+      throw StateError('Failed to complete within $msg');
     });
   }
 
@@ -31,7 +31,7 @@
         return await f();
       } catch (_) {
         if (keepGoing) {
-          await new Future<dynamic>.delayed(interval);
+          await Future<dynamic>.delayed(interval);
         }
       }
     }
@@ -43,10 +43,10 @@
 /// Potentially useful as a means to extract it from log statements.
 Uri extractObservatoryUri(String str) {
   const kObservatoryListening = 'Observatory listening on ';
-  int msgPos = str.indexOf(kObservatoryListening);
+  final msgPos = str.indexOf(kObservatoryListening);
   if (msgPos == -1) return null;
-  int startPos = msgPos + kObservatoryListening.length;
-  int endPos = str.indexOf(new RegExp(r'(\s|$)'), startPos);
+  final startPos = msgPos + kObservatoryListening.length;
+  final endPos = str.indexOf(RegExp(r'(\s|$)'), startPos);
   try {
     return Uri.parse(str.substring(startPos, endPos));
   } on FormatException {
diff --git a/coverage/pubspec.yaml b/coverage/pubspec.yaml
index 0d203b4..3b87e2f 100644
--- a/coverage/pubspec.yaml
+++ b/coverage/pubspec.yaml
@@ -1,19 +1,23 @@
 name: coverage
-version: 0.12.4
+version: 0.13.0
 author: Dart Team <misc@dartlang.org>
 description: Coverage data manipulation and formatting
 homepage: https://github.com/dart-lang/coverage
+
 environment:
-  sdk: '>=2.0.0-dev.64.1 <3.0.0'
+  sdk: '>=2.0.0 <3.0.0'
+
 dependencies:
   args: '>=1.4.0 <2.0.0'
   logging: '>=0.9.0 <0.12.0'
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
   stack_trace: ^1.3.0
-  vm_service_client: ^0.2.2+1
+  vm_service_lib: ^3.21.0
+
 dev_dependencies:
   test: ^1.0.0
+
 executables:
   collect_coverage:
   format_coverage:
diff --git a/coverage/tool/travis.sh b/coverage/tool/travis.sh
index a2499e8..0c25614 100755
--- a/coverage/tool/travis.sh
+++ b/coverage/tool/travis.sh
@@ -34,7 +34,7 @@
   echo "Collecting coverage on port $OBS_PORT..."
 
   # Start tests in one VM.
-  dart \
+  dart --disable-service-auth-codes \
     --enable-vm-service=$OBS_PORT \
     --pause-isolates-on-exit \
     test/test_all.dart &
diff --git a/csslib/BUILD.gn b/csslib/BUILD.gn
index e3bcecd..74b3f9d 100644
--- a/csslib/BUILD.gn
+++ b/csslib/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for csslib-0.16.0
+# This file is generated by importer.py for csslib-0.16.1
 
 import("//build/dart/dart_library.gni")
 
diff --git a/csslib/CHANGELOG.md b/csslib/CHANGELOG.md
index 162975f..783393d 100644
--- a/csslib/CHANGELOG.md
+++ b/csslib/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.16.1
+	
+- Fixed a crash caused by parsing certain calc() expressions and variables names that contain numbers.
+
 ## 0.16.0
 
 - Removed support for the shadow-piercing comibnators `/deep/` and `>>>`. These
diff --git a/csslib/lib/parser.dart b/csslib/lib/parser.dart
index fbf291c..d8ba671 100644
--- a/csslib/lib/parser.dart
+++ b/csslib/lib/parser.dart
@@ -1681,14 +1681,8 @@
       }
 
       if (keepParsing && value != null) {
-        LiteralTerm unitTerm;
-        // Don't process the dimension if MINUS or PLUS is next.
-        if (_peek() != TokenKind.MINUS && _peek() != TokenKind.PLUS) {
-          unitTerm = processDimension(termToken, value, _makeSpan(start));
-        }
-        if (unitTerm == null) {
-          unitTerm = LiteralTerm(value, value.name, _makeSpan(start));
-        }
+        LiteralTerm unitTerm =
+            processDimension(termToken, value, _makeSpan(start));
         expressions.add(unitTerm);
 
         value = null;
@@ -2498,12 +2492,13 @@
         _next(); // Skip the unit
         break;
       default:
-        if (value != null && t != null) {
-          term = (value is Identifier)
-              ? LiteralTerm(value, value.name, span)
-              : NumberTerm(value, t.text, span);
+        if (value != null) {
+          if (value is Identifier) {
+            term = LiteralTerm(value, value.name, span);
+          } else if (t != null) {
+            term = NumberTerm(value, t.text, span);
+          }
         }
-        break;
     }
 
     return term;
diff --git a/csslib/lib/src/tree_base.dart b/csslib/lib/src/tree_base.dart
index d8fee1d..5011f3d 100644
--- a/csslib/lib/src/tree_base.dart
+++ b/csslib/lib/src/tree_base.dart
@@ -57,21 +57,23 @@
   }
 
   String toValue(value) {
-    if (value == null)
+    if (value == null) {
       return 'null';
-    else if (value is Identifier)
+    } else if (value is Identifier) {
       return value.name;
-    else
+    } else {
       return value.toString();
+    }
   }
 
   void writeNode(String label, TreeNode node) {
     write('${label}: ');
     depth += 1;
-    if (node != null)
+    if (node != null) {
       node.visit(printer);
-    else
+    } else {
       writeln('null');
+    }
     depth -= 1;
   }
 
diff --git a/csslib/pubspec.yaml b/csslib/pubspec.yaml
index 8ce1c79..f4c6d83 100644
--- a/csslib/pubspec.yaml
+++ b/csslib/pubspec.yaml
@@ -1,5 +1,5 @@
 name: csslib
-version: 0.16.0
+version: 0.16.1
 
 description: A library for parsing CSS.
 author: Dart Team <misc@dartlang.org>
diff --git a/dart_style/BUILD.gn b/dart_style/BUILD.gn
index 2b32eba..bfc42f4 100644
--- a/dart_style/BUILD.gn
+++ b/dart_style/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for dart_style-1.2.8
+# This file is generated by importer.py for dart_style-1.2.9
 
 import("//build/dart/dart_library.gni")
 
diff --git a/dart_style/CHANGELOG.md b/dart_style/CHANGELOG.md
index e31a726..993eafc 100644
--- a/dart_style/CHANGELOG.md
+++ b/dart_style/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 1.2.9
+
+* Support `package:analyzer` `0.37.0`.
+
 # 1.2.8
 
 * Better indentation of function expressions inside trailing comma argument
diff --git a/dart_style/codereview.settings b/dart_style/codereview.settings
deleted file mode 100644
index 25510f0..0000000
--- a/dart_style/codereview.settings
+++ /dev/null
@@ -1,3 +0,0 @@
-CODE_REVIEW_SERVER: https://codereview.chromium.org/
-VIEW_VC: https://github.com/dart-lang/dart_style/commit/
-CC_LIST: reviews@dartlang.org
diff --git a/dart_style/lib/src/source_visitor.dart b/dart_style/lib/src/source_visitor.dart
index 47230c6..ffef68d 100644
--- a/dart_style/lib/src/source_visitor.dart
+++ b/dart_style/lib/src/source_visitor.dart
@@ -1162,9 +1162,8 @@
     var requiredParams = node.parameters
         .where((param) => param is! DefaultFormalParameter)
         .toList();
-    var optionalParams = node.parameters
-        .where((param) => param is DefaultFormalParameter)
-        .toList();
+    var optionalParams =
+        node.parameters.whereType<DefaultFormalParameter>().toList();
 
     if (nestExpression) builder.nestExpression();
     token(node.leftParenthesis);
diff --git a/dart_style/pubspec.yaml b/dart_style/pubspec.yaml
index 3f2b24c..71eb65a 100644
--- a/dart_style/pubspec.yaml
+++ b/dart_style/pubspec.yaml
@@ -1,6 +1,6 @@
 name: dart_style
 # Note: See tool/grind.dart for how to bump the version.
-version: 1.2.8
+version: 1.2.9
 author: Dart Team <misc@dartlang.org>
 description: >-
   Opinionated, automatic Dart source code formatter.
@@ -11,7 +11,7 @@
   sdk: '>=2.3.0 <3.0.0'
 
 dependencies:
-  analyzer: '>=0.36.3 <0.37.0'
+  analyzer: '>=0.36.3 <0.38.0'
   args: '>=0.12.1 <2.0.0'
   path: ^1.0.0
   source_span: ^1.4.0
diff --git a/protobuf/BUILD.gn b/protobuf/BUILD.gn
index 4dfa2da..ba921a0 100644
--- a/protobuf/BUILD.gn
+++ b/protobuf/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for protobuf-0.13.12
+# This file is generated by importer.py for protobuf-0.13.15
 
 import("//build/dart/dart_library.gni")
 
diff --git a/protobuf/CHANGELOG.md b/protobuf/CHANGELOG.md
index a151f52..06ed05d 100644
--- a/protobuf/CHANGELOG.md
+++ b/protobuf/CHANGELOG.md
@@ -1,3 +1,16 @@
+## 0.13.15
+
+* Add new getter `GeneratedMessage.isFrozen` to query if the message has been frozen. 
+
+## 0.13.14
+
+* Avoid needless copy when reading from a Uint8List buffer.
+
+## 0.13.13
+
+* `Added `ExtensionRegistry.reparseMessage()` for decoding extensions from unknown fields after the initial
+   decoding.
+
 ## 0.13.12
 
 * `BuilderInfo.add` now ignores fields with tag number 0.
diff --git a/protobuf/lib/meta.dart b/protobuf/lib/meta.dart
index f50bc77..920ac6e 100644
--- a/protobuf/lib/meta.dart
+++ b/protobuf/lib/meta.dart
@@ -36,6 +36,7 @@
   'hasRequiredFields',
   'hashCode',
   'info_',
+  'isFrozen',
   'isInitialized',
   'mergeFromBuffer',
   'mergeFromCodedBufferReader',
diff --git a/protobuf/lib/src/protobuf/coded_buffer_reader.dart b/protobuf/lib/src/protobuf/coded_buffer_reader.dart
index aae3e98..94dcc30 100644
--- a/protobuf/lib/src/protobuf/coded_buffer_reader.dart
+++ b/protobuf/lib/src/protobuf/coded_buffer_reader.dart
@@ -19,8 +19,7 @@
   CodedBufferReader(List<int> buffer,
       {int recursionLimit = DEFAULT_RECURSION_LIMIT,
       int sizeLimit = DEFAULT_SIZE_LIMIT})
-      : _buffer = buffer is Uint8List ? buffer : Uint8List(buffer.length)
-          ..setRange(0, buffer.length, buffer),
+      : _buffer = buffer is Uint8List ? buffer : Uint8List.fromList(buffer),
         _recursionLimit = recursionLimit,
         _sizeLimit = math.min(sizeLimit, buffer.length) {
     _currentLimit = _sizeLimit;
diff --git a/protobuf/lib/src/protobuf/extension_registry.dart b/protobuf/lib/src/protobuf/extension_registry.dart
index 243d609..0892c2d 100644
--- a/protobuf/lib/src/protobuf/extension_registry.dart
+++ b/protobuf/lib/src/protobuf/extension_registry.dart
@@ -33,13 +33,91 @@
     }
     return null;
   }
+
+  /// Returns a shallow copy of [message], with all extensions in [this] parsed
+  /// from the unknown fields of [message].
+  ///
+  /// Extensions already present in [message] will be preserved.
+  ///
+  /// If [message] is frozen, the result will be as well.
+  ///
+  /// Throws an [InvalidProtocolBufferException] if the parsed extensions are
+  /// malformed.
+  ///
+  /// Using this method to retrieve extensions is more expensive overall than
+  /// using an [ExtensionRegistry] with all the needed extensions when doing
+  /// [GeneratedMessage.fromBuffer].
+  ///
+  /// Example:
+  ///
+  /// `foo.proto`
+  /// ```proto
+  /// syntax = "proto2";
+  ///
+  /// message Foo {
+  ///   extensions 1 to max;
+  /// }
+  ///
+  /// extend Foo {
+  ///   optional string val1 = 1;
+  ///   optional string val2 = 2;
+  /// }
+  /// ```
+  /// `main.dart`
+  /// ```
+  /// import 'package:protobuf/protobuf.dart';
+  /// import 'package:test/test.dart';
+  /// import 'src/generated/sample.pb.dart';
+  ///
+  /// void main() {
+  ///   ExtensionRegistry r1 = ExtensionRegistry()..add(Sample.val1);
+  ///   ExtensionRegistry r2 = ExtensionRegistry()..add(Sample.val2);
+  ///   Foo original = Foo()..setExtension(Sample.val1, 'a')..setExtension(Sample.val2, 'b');
+  ///   Foo withUnknownFields = Foo.fromBuffer(original.writeToBuffer());
+  ///   Foo reparsed1 = r1.reparseMessage(withUnknownFields);
+  ///   Foo reparsed2 = r2.reparseMessage(reparsed1);
+  ///   expect(withUnknownFields.hasExtension(Sample.val1), isFalse);
+  ///   expect(withUnknownFields.hasExtension(Sample.val2), isFalse);
+  ///   expect(reparsed1.hasExtension(Sample.val1), isTrue);
+  ///   expect(reparsed1.hasExtension(Sample.val2), isFalse);
+  ///   expect(reparsed2.hasExtension(Sample.val1), isTrue);
+  ///   expect(reparsed2.hasExtension(Sample.val2), isTrue);
+  /// }
+  /// ```
+  T reparseMessage<T extends GeneratedMessage>(T message) =>
+      _reparseMessage(message, this);
+}
+
+T _reparseMessage<T extends GeneratedMessage>(
+    T message, ExtensionRegistry extensionRegistry) {
+  T result = message.createEmptyInstance();
+
+  result._fieldSet._shallowCopyValues(message._fieldSet);
+  UnknownFieldSet resultUnknownFields = result._fieldSet._unknownFields;
+  if (resultUnknownFields != null) {
+    CodedBufferWriter codedBufferWriter = CodedBufferWriter();
+    extensionRegistry._extensions[message.info_.qualifiedMessageName]
+        ?.forEach((tagNumber, extension) {
+      final UnknownFieldSetField unknownField =
+          resultUnknownFields._fields[tagNumber];
+      if (unknownField != null) {
+        unknownField.writeTo(tagNumber, codedBufferWriter);
+      }
+      resultUnknownFields._fields.remove(tagNumber);
+    });
+
+    result.mergeFromBuffer(codedBufferWriter.toBuffer(), extensionRegistry);
+  }
+  if (message._fieldSet._isReadOnly) {
+    result.freeze();
+  }
+  return result;
 }
 
 class _EmptyExtensionRegistry implements ExtensionRegistry {
   const _EmptyExtensionRegistry();
 
-  // Needed to quiet missing member warning.
-  get _extensions => null;
+  get _extensions => const <String, Map<int, Extension>>{};
 
   void add(Extension extension) {
     throw UnsupportedError('Immutable ExtensionRegistry');
@@ -50,4 +128,7 @@
   }
 
   Extension getExtension(String messageName, int tagNumber) => null;
+
+  T reparseMessage<T extends GeneratedMessage>(T message) =>
+      _reparseMessage(message, this);
 }
diff --git a/protobuf/lib/src/protobuf/field_set.dart b/protobuf/lib/src/protobuf/field_set.dart
index 1b76048..97071c6 100644
--- a/protobuf/lib/src/protobuf/field_set.dart
+++ b/protobuf/lib/src/protobuf/field_set.dart
@@ -797,5 +797,7 @@
     if (original._hasUnknownFields) {
       _ensureUnknownFields()._fields?.addAll(original._unknownFields._fields);
     }
+
+    _oneofCases?.addAll(original._oneofCases);
   }
 }
diff --git a/protobuf/lib/src/protobuf/generated_message.dart b/protobuf/lib/src/protobuf/generated_message.dart
index 1ad45fe..24d1d1f 100644
--- a/protobuf/lib/src/protobuf/generated_message.dart
+++ b/protobuf/lib/src/protobuf/generated_message.dart
@@ -61,6 +61,13 @@
     return this;
   }
 
+  /// Returns `true` if this message is marked read-only. Otherwise `false`.
+  ///
+  /// Even when `false`, some sub-message could be read-only.
+  ///
+  /// If `true` all sub-messages are frozen.
+  bool get isFrozen => _fieldSet._isReadOnly;
+
   /// Returns a writable, shallow copy of this message.
   ///
   /// Sub messages will be shared with [this] and will still be frozen if [this]
diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml
index 20e8044..4e2a03f 100644
--- a/protobuf/pubspec.yaml
+++ b/protobuf/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protobuf
-version: 0.13.12
+version: 0.13.15
 author: Dart Team <misc@dartlang.org>
 description: >
   Runtime library for protocol buffers support.
diff --git a/url_launcher/BUILD.gn b/url_launcher/BUILD.gn
index e5d1a3b..f3483cb 100644
--- a/url_launcher/BUILD.gn
+++ b/url_launcher/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for url_launcher-5.0.3
+# This file is generated by importer.py for url_launcher-5.0.5
 
 import("//build/dart/dart_library.gni")
 
diff --git a/url_launcher/CHANGELOG.md b/url_launcher/CHANGELOG.md
index 23cfe54..20b64b1 100644
--- a/url_launcher/CHANGELOG.md
+++ b/url_launcher/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 5.0.5
+
+* Add `enableDomStorage` field to `launch` to enable DOM storage in Android WebView.
+
+## 5.0.4
+
+* Update Dart code to conform to current Dart formatter.
+
 ## 5.0.3
 
 * Add missing template type parameter to `invokeMethod` calls.
@@ -5,6 +13,7 @@
 * Replace invokeMethod with invokeMapMethod wherever necessary.
 
 ## 5.0.2
+
 * Fixes `closeWebView` failure on iOS.
 
 ## 5.0.1
diff --git a/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java b/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java
index 888d3c3..30d0676 100644
--- a/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java
+++ b/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java
@@ -68,6 +68,7 @@
     Intent launchIntent;
     boolean useWebView = call.argument("useWebView");
     boolean enableJavaScript = call.argument("enableJavaScript");
+    boolean enableDomStorage = call.argument("enableDomStorage");
     Activity activity = mRegistrar.activity();
     if (activity == null) {
       result.error("NO_ACTIVITY", "Launching a URL requires a foreground activity.", null);
@@ -77,6 +78,7 @@
       launchIntent = new Intent(activity, WebViewActivity.class);
       launchIntent.putExtra("url", url);
       launchIntent.putExtra("enableJavaScript", enableJavaScript);
+      launchIntent.putExtra("enableDomStorage", enableDomStorage);
     } else {
       launchIntent = new Intent(Intent.ACTION_VIEW);
       launchIntent.setData(Uri.parse(url));
@@ -105,10 +107,14 @@
       Intent intent = getIntent();
       String url = intent.getStringExtra("url");
       Boolean enableJavaScript = intent.getBooleanExtra("enableJavaScript", false);
+      Boolean enableDomStorage = intent.getBooleanExtra("enableDomStorage", false);
       webview.loadUrl(url);
       if (enableJavaScript) {
         webview.getSettings().setJavaScriptEnabled(enableJavaScript);
       }
+      if (enableDomStorage) {
+        webview.getSettings().setDomStorageEnabled(enableDomStorage);
+      }
       // Open new urls inside the webview itself.
       webview.setWebViewClient(
           new WebViewClient() {
diff --git a/url_launcher/example/lib/main.dart b/url_launcher/example/lib/main.dart
index 6ef6790..66b5e9f 100644
--- a/url_launcher/example/lib/main.dart
+++ b/url_launcher/example/lib/main.dart
@@ -65,6 +65,19 @@
     }
   }
 
+  Future<void> _launchInWebViewWithDomStorage(String url) async {
+    if (await canLaunch(url)) {
+      await launch(
+        url,
+        forceSafariVC: true,
+        forceWebView: true,
+        enableDomStorage: true,
+      );
+    } else {
+      throw 'Could not launch $url';
+    }
+  }
+
   Future<void> _launchUniversalLinkIos(String url) async {
     if (await canLaunch('https://youtube.com')) {
       final bool nativeAppLaunchSucceeded = await launch(
@@ -104,69 +117,77 @@
       appBar: AppBar(
         title: Text(widget.title),
       ),
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            Padding(
-              padding: const EdgeInsets.all(16.0),
-              child: TextField(
-                  onChanged: (String text) => _phone = text,
-                  decoration: const InputDecoration(
-                      hintText: 'Input the phone number to launch')),
-            ),
-            RaisedButton(
-              onPressed: () => setState(() {
-                    _launched = _makePhoneCall('tel:$_phone');
-                  }),
-              child: const Text('Make phone call'),
-            ),
-            const Padding(
-              padding: EdgeInsets.all(16.0),
-              child: Text(toLaunch),
-            ),
-            RaisedButton(
-              onPressed: () => setState(() {
-                    _launched = _launchInBrowser(toLaunch);
-                  }),
-              child: const Text('Launch in browser'),
-            ),
-            const Padding(padding: EdgeInsets.all(16.0)),
-            RaisedButton(
-              onPressed: () => setState(() {
-                    _launched = _launchInWebViewOrVC(toLaunch);
-                  }),
-              child: const Text('Launch in app'),
-            ),
-            const Padding(padding: EdgeInsets.all(16.0)),
-            RaisedButton(
-              onPressed: () => setState(() {
-                    _launched = _launchInWebViewWithJavaScript(toLaunch);
-                  }),
-              child: const Text('Launch in app(JavaScript ON)'),
-            ),
-            RaisedButton(
-              onPressed: () => setState(() {
-                    _launched = _launchUniversalLinkIos(toLaunch);
-                  }),
-              child: const Text(
-                  'Launch a universal link in a native app, fallback to Safari.(Youtube)'),
-            ),
-            const Padding(padding: EdgeInsets.all(16.0)),
-            RaisedButton(
-              onPressed: () => setState(() {
-                    _launched = _launchInWebViewOrVC(toLaunch);
-                    Timer(const Duration(seconds: 5), () {
-                      print('Closing WebView after 5 seconds...');
-                      closeWebView();
-                    });
-                  }),
-              child: const Text('Launch in app + close after 5 seconds'),
-            ),
-            const Padding(padding: EdgeInsets.all(16.0)),
-            FutureBuilder<void>(future: _launched, builder: _launchStatus),
-          ],
-        ),
+      body: ListView(
+        children: <Widget>[
+          Column(
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: <Widget>[
+              Padding(
+                padding: const EdgeInsets.all(16.0),
+                child: TextField(
+                    onChanged: (String text) => _phone = text,
+                    decoration: const InputDecoration(
+                        hintText: 'Input the phone number to launch')),
+              ),
+              RaisedButton(
+                onPressed: () => setState(() {
+                  _launched = _makePhoneCall('tel:$_phone');
+                }),
+                child: const Text('Make phone call'),
+              ),
+              const Padding(
+                padding: EdgeInsets.all(16.0),
+                child: Text(toLaunch),
+              ),
+              RaisedButton(
+                onPressed: () => setState(() {
+                  _launched = _launchInBrowser(toLaunch);
+                }),
+                child: const Text('Launch in browser'),
+              ),
+              const Padding(padding: EdgeInsets.all(16.0)),
+              RaisedButton(
+                onPressed: () => setState(() {
+                  _launched = _launchInWebViewOrVC(toLaunch);
+                }),
+                child: const Text('Launch in app'),
+              ),
+              RaisedButton(
+                onPressed: () => setState(() {
+                  _launched = _launchInWebViewWithJavaScript(toLaunch);
+                }),
+                child: const Text('Launch in app(JavaScript ON)'),
+              ),
+              RaisedButton(
+                onPressed: () => setState(() {
+                  _launched = _launchInWebViewWithDomStorage(toLaunch);
+                }),
+                child: const Text('Launch in app(DOM storage ON)'),
+              ),
+              const Padding(padding: EdgeInsets.all(16.0)),
+              RaisedButton(
+                onPressed: () => setState(() {
+                  _launched = _launchUniversalLinkIos(toLaunch);
+                }),
+                child: const Text(
+                    'Launch a universal link in a native app, fallback to Safari.(Youtube)'),
+              ),
+              const Padding(padding: EdgeInsets.all(16.0)),
+              RaisedButton(
+                onPressed: () => setState(() {
+                  _launched = _launchInWebViewOrVC(toLaunch);
+                  Timer(const Duration(seconds: 5), () {
+                    print('Closing WebView after 5 seconds...');
+                    closeWebView();
+                  });
+                }),
+                child: const Text('Launch in app + close after 5 seconds'),
+              ),
+              const Padding(padding: EdgeInsets.all(16.0)),
+              FutureBuilder<void>(future: _launched, builder: _launchStatus),
+            ],
+          ),
+        ],
       ),
     );
   }
diff --git a/url_launcher/lib/url_launcher.dart b/url_launcher/lib/url_launcher.dart
index a942b50..edae489 100644
--- a/url_launcher/lib/url_launcher.dart
+++ b/url_launcher/lib/url_launcher.dart
@@ -42,6 +42,8 @@
 /// WebViews.
 /// [enableJavaScript] is an Android only setting. If true, WebView enable
 /// javascript.
+/// [enableDomStorage] is an Android only setting. If true, WebView enable
+/// DOM storage.
 ///
 /// Note that if any of the above are set to true but the URL is not a web URL,
 /// this will throw a [PlatformException].
@@ -57,6 +59,7 @@
   bool forceSafariVC,
   bool forceWebView,
   bool enableJavaScript,
+  bool enableDomStorage,
   bool universalLinksOnly,
   Brightness statusBarBrightness,
 }) async {
@@ -86,6 +89,7 @@
       'useSafariVC': forceSafariVC ?? isWebURL,
       'useWebView': forceWebView ?? false,
       'enableJavaScript': enableJavaScript ?? false,
+      'enableDomStorage': enableDomStorage ?? false,
       'universalLinksOnly': universalLinksOnly ?? false,
     },
   );
diff --git a/url_launcher/pubspec.yaml b/url_launcher/pubspec.yaml
index f67afe5..0c07112 100644
--- a/url_launcher/pubspec.yaml
+++ b/url_launcher/pubspec.yaml
@@ -3,7 +3,7 @@
   web, phone, SMS, and email schemes.
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher
-version: 5.0.3
+version: 5.0.5
 
 flutter:
   plugin:
diff --git a/vm_service_lib/BUILD.gn b/vm_service_lib/BUILD.gn
index 0f1329e..5541891 100644
--- a/vm_service_lib/BUILD.gn
+++ b/vm_service_lib/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for vm_service_lib-3.21.0
+# This file is generated by importer.py for vm_service_lib-3.22.0
 
 import("//build/dart/dart_library.gni")
 
diff --git a/vm_service_lib/CHANGELOG.md b/vm_service_lib/CHANGELOG.md
index 5b5d6c7..e4a47b4 100644
--- a/vm_service_lib/CHANGELOG.md
+++ b/vm_service_lib/CHANGELOG.md
@@ -1,5 +1,16 @@
 # Changelog
 
+## 3.22.0
+- The `registerService` RPC and `Service` stream are now public.
+- `Event` has been updated to include the optional `service`, `method`, and
+  `alias` properties.
+
+## 3.21.1
+- **breaking**: Fixed issue where an `InstanceRef` of type `null` could be returned
+  instead of null for non-`InstanceRef` properties and return values. As a
+  result, some property and return types have been changed from Obj to their
+  correct types.
+
 ## 3.21.0
 - support service protocol version 3.21
 
diff --git a/vm_service_lib/example/vm_service_assert.dart b/vm_service_lib/example/vm_service_assert.dart
index 613defc..0357cf4 100644
--- a/vm_service_lib/example/vm_service_assert.dart
+++ b/vm_service_lib/example/vm_service_assert.dart
@@ -600,6 +600,7 @@
   assertString(obj.type);
   assertString(obj.id);
   assertInstanceKind(obj.kind);
+  assertClassRef(obj.classRef);
   return obj;
 }
 
@@ -757,6 +758,7 @@
   assertString(obj.id);
   assertInstanceKind(obj.kind);
   assertClassRef(obj.classRef);
+  assertString(obj.valueAsString);
   return obj;
 }
 
@@ -772,6 +774,8 @@
   assertString(obj.type);
   assertString(obj.id);
   assertInstanceKind(obj.kind);
+  assertClassRef(obj.classRef);
+  assertString(obj.valueAsString);
   return obj;
 }
 
diff --git a/vm_service_lib/example/vm_service_lib_tester.dart b/vm_service_lib/example/vm_service_lib_tester.dart
index 898af1b..7b22ae2 100644
--- a/vm_service_lib/example/vm_service_lib_tester.dart
+++ b/vm_service_lib/example/vm_service_lib_tester.dart
@@ -76,7 +76,8 @@
       expect(originalJson, isNotNull, reason: 'Unrecognized event type! $json');
 
       // ignore: invalid_use_of_visible_for_testing_member
-      var instance = createServiceObject(originalJson);
+      var instance =
+          createServiceObject(originalJson, const ['Event', 'Success']);
       expect(instance, isNotNull,
           reason: 'failed to deserialize object $originalJson!');
 
diff --git a/vm_service_lib/lib/vm_service_lib.dart b/vm_service_lib/lib/vm_service_lib.dart
index 6f72fe9..5b78bb0 100644
--- a/vm_service_lib/lib/vm_service_lib.dart
+++ b/vm_service_lib/lib/vm_service_lib.dart
@@ -17,7 +17,7 @@
 
 export 'src/service_extension_registry.dart' show ServiceExtensionRegistry;
 
-const String vmServiceVersion = '3.21.0';
+const String vmServiceVersion = '3.22.0';
 
 /// @optional
 const String optional = 'optional';
@@ -29,13 +29,20 @@
 /// This is useful for handling the results of the Stdout or Stderr events.
 String decodeBase64(String str) => utf8.decode(base64.decode(str));
 
-Object createServiceObject(dynamic json) {
+// Returns true if a response is the Dart `null` instance.
+bool _isNullInstance(Map json) =>
+    ((json['type'] == '@Instance') && (json['kind'] == 'Null'));
+
+Object createServiceObject(dynamic json, List<String> expectedTypes) {
   if (json == null) return null;
 
   if (json is List) {
-    return json.map((e) => createServiceObject(e)).toList();
+    return json.map((e) => createServiceObject(e, expectedTypes)).toList();
   } else if (json is Map) {
     String type = json['type'];
+    if (_isNullInstance(json) && (!expectedTypes.contains(type))) {
+      return null;
+    }
     if (_typeFactories[type] == null) {
       return null;
     } else {
@@ -142,6 +149,48 @@
   'HeapSpace': HeapSpace.parse,
 };
 
+Map<String, List<String>> _methodReturnTypes = {
+  'addBreakpoint': const ['Breakpoint'],
+  'addBreakpointWithScriptUri': const ['Breakpoint'],
+  'addBreakpointAtEntry': const ['Breakpoint'],
+  'clearVMTimeline': const ['Success'],
+  'invoke': const ['InstanceRef', 'ErrorRef', 'Sentinel'],
+  'evaluate': const ['InstanceRef', 'ErrorRef', 'Sentinel'],
+  'evaluateInFrame': const ['InstanceRef', 'ErrorRef', 'Sentinel'],
+  'getAllocationProfile': const ['AllocationProfile'],
+  'getFlagList': const ['FlagList'],
+  'getInstances': const ['InstanceSet'],
+  'getIsolate': const ['Isolate', 'Sentinel'],
+  'getMemoryUsage': const ['MemoryUsage', 'Sentinel'],
+  'getScripts': const ['ScriptList'],
+  'getObject': const ['Obj', 'Sentinel'],
+  'getStack': const ['Stack'],
+  'getSourceReport': const ['SourceReport'],
+  'getVersion': const ['Version'],
+  'getVM': const ['VM'],
+  'getVMTimeline': const ['Timeline'],
+  'getVMTimelineFlags': const ['TimelineFlags'],
+  'getVMTimelineMicros': const ['Timestamp'],
+  'pause': const ['Success'],
+  'kill': const ['Success'],
+  'reloadSources': const ['ReloadReport'],
+  'removeBreakpoint': const ['Success'],
+  'resume': const ['Success'],
+  'setExceptionPauseMode': const ['Success'],
+  'setFlag': const ['Success'],
+  'setLibraryDebuggable': const ['Success'],
+  'setName': const ['Success'],
+  'setVMName': const ['Success'],
+  'setVMTimelineFlags': const ['Success'],
+  'streamCancel': const ['Success'],
+  'streamListen': const ['Success'],
+  '_collectAllGarbage': const ['Success'],
+  '_requestHeapSnapshot': const ['Success'],
+  '_clearCpuProfile': const ['Success'],
+  '_getCpuProfile': const ['_CpuProfile'],
+  '_registerService': const ['Success'],
+};
+
 /// A class representation of the Dart VM Service Protocol.
 ///
 /// Both clients and servers should implement this interface.
@@ -242,9 +291,8 @@
   ///
   /// If `disableBreakpoints` is provided and set to true, any breakpoints hit
   /// as a result of this invocation are ignored, including pauses resulting
-  /// from a call to <code>debugger()</code>debugger() from
-  /// <code>dart:developer</code>dart:developer. Defaults to false if not
-  /// provided.
+  /// from a call to `debugger()` from `dart:developer`. Defaults to false if
+  /// not provided.
   ///
   /// If `targetId` or any element of `argumentIds` is a temporary id which has
   /// expired, then the `Expired` [Sentinel] is returned.
@@ -364,9 +412,8 @@
   /// The `getInstances` RPC is used to retrieve a set of instances which are of
   /// a specific type.
   ///
-  /// `objectId` is the ID of the <code>Class</code>Class to retrieve instances
-  /// for. `objectId` must be the ID of a <code>Class</code>Class, otherwise an
-  /// error is returned.
+  /// `objectId` is the ID of the `Class` to retrieve instances for. `objectId`
+  /// must be the ID of a `Class`, otherwise an error is returned.
   ///
   /// `limit` is the maximum number of instances to be returned.
   ///
@@ -495,19 +542,16 @@
   ///
   /// The `timeOriginMicros` parameter is the beginning of the time range used
   /// to filter timeline events. It uses the same monotonic clock as
-  /// dart:developer's <code>Timeline.now</code>Timeline.now and the VM
-  /// embedding API's <code>Dart_TimelineGetMicros</code>Dart_TimelineGetMicros.
-  /// See [getVMTimelineMicros] for access to this clock through the service
-  /// protocol.
+  /// dart:developer's `Timeline.now` and the VM embedding API's
+  /// `Dart_TimelineGetMicros`. See [getVMTimelineMicros] for access to this
+  /// clock through the service protocol.
   ///
   /// The `timeExtentMicros` parameter specifies how large the time range used
   /// to filter timeline events should be.
   ///
   /// For example, given `timeOriginMicros` and `timeExtentMicros`, only
   /// timeline events from the following time range will be returned:
-  /// <code>(timeOriginMicros, timeOriginMicros +
-  /// timeExtentMicros)</code>(timeOriginMicros, timeOriginMicros +
-  /// timeExtentMicros).
+  /// `(timeOriginMicros, timeOriginMicros + timeExtentMicros)`.
   ///
   /// If `getVMTimeline` is invoked while the current recorder is one of Fuchsia
   /// or Systrace, the `114` error code, invalid timeline request, will be
@@ -524,11 +568,8 @@
   Future<TimelineFlags> getVMTimelineFlags();
 
   /// The `getVMTimelineMicros` RPC returns the current time stamp from the
-  /// clock used by the timeline, similar to
-  /// <code>Timeline.now</code>Timeline.now in
-  /// <code>dart:developer</code>dart:developer and
-  /// <code>Dart_TimelineGetMicros</code>Dart_TimelineGetMicros in the VM
-  /// embedding API.
+  /// clock used by the timeline, similar to `Timeline.now` in `dart:developer`
+  /// and `Dart_TimelineGetMicros` in the VM embedding API.
   ///
   /// See [Timestamp] and [getVMTimeline].
   Future<Timestamp> getVMTimelineMicros();
@@ -543,13 +584,23 @@
   Future<Success> pause(String isolateId);
 
   /// The `kill` RPC is used to kill an isolate as if by dart:isolate's
-  /// <code>Isolate.kill(IMMEDIATE)</code>Isolate.kill(IMMEDIATE).
+  /// `Isolate.kill(IMMEDIATE)`.
   ///
   /// The isolate is killed regardless of whether it is paused or running.
   ///
   /// See [Success].
   Future<Success> kill(String isolateId);
 
+  /// Registers a service that can be invoked by other VM service clients, where
+  /// `service` is the name of the service to advertise and `alias` is an
+  /// alternative name for the registered service.
+  ///
+  /// Requests made to the new service will be forwarded to the client which
+  /// originally registered the service.
+  ///
+  /// See [Success].
+  Future<Success> registerService(String service, String alias);
+
   /// The `reloadSources` RPC is used to perform a hot reload of an Isolate's
   /// sources.
   ///
@@ -681,6 +732,7 @@
   /// Extension | Extension
   /// Timeline | TimelineEvents
   /// Logging | Logging
+  /// Service | ServiceRegistered, ServiceUnregistered
   ///
   /// Additionally, some embedders provide the `Stdout` and `Stderr` streams.
   /// These streams allow the client to subscribe to writes to stdout and
@@ -713,8 +765,6 @@
   /// `tags` is one of UserVM, UserOnly, VMUser, VMOnly, or None.
   @undocumented
   Future<CpuProfile> getCpuProfile(String isolateId, String tags);
-  @undocumented
-  Future<Success> registerService(String service, String alias);
 }
 
 /// A Dart VM Service Protocol connection that delegates requests to a
@@ -927,6 +977,12 @@
             params['isolateId'],
           );
           break;
+        case 'registerService':
+          response = await _serviceImplementation.registerService(
+            params['service'],
+            params['alias'],
+          );
+          break;
         case 'reloadSources':
           response = await _serviceImplementation.reloadSources(
             params['isolateId'],
@@ -1120,6 +1176,9 @@
   // Logging
   Stream<Event> get onLoggingEvent => _getEventController('Logging').stream;
 
+  // ServiceRegistered, ServiceUnregistered
+  Stream<Event> get onServiceEvent => _getEventController('Service').stream;
+
   // WriteEvent
   Stream<Event> get onStdoutEvent => _getEventController('Stdout').stream;
 
@@ -1348,6 +1407,11 @@
   }
 
   @override
+  Future<Success> registerService(String service, String alias) {
+    return _call('registerService', {'service': service, 'alias': alias});
+  }
+
+  @override
   Future<ReloadReport> reloadSources(
     String isolateId, {
     bool force,
@@ -1466,12 +1530,6 @@
     return _call('_getCpuProfile', {'isolateId': isolateId, 'tags': tags});
   }
 
-  @undocumented
-  @override
-  Future<Success> registerService(String service, String alias) {
-    return _call('_registerService', {'service': service, 'alias': alias});
-  }
-
   /// Call an arbitrary service protocol method. This allows clients to call
   /// methods not explicitly exposed by this library.
   Future<Response> callMethod(String method, {String isolateId, Map args}) {
@@ -1557,7 +1615,8 @@
       String streamId = map['params']['streamId'];
       Map event = map['params']['event'];
       event['_data'] = data;
-      _getEventController(streamId).add(createServiceObject(event));
+      _getEventController(streamId)
+          .add(createServiceObject(event, const ['Event']));
     }
   }
 
@@ -1589,7 +1648,7 @@
   void _processResponse(Map<String, dynamic> json) {
     Completer completer = _completers.remove(json['id']);
     String methodName = _methodCalls.remove(json['id']);
-
+    List<String> returnTypes = _methodReturnTypes[methodName];
     if (completer == null) {
       _log.severe('unmatched request response: ${jsonEncode(json)}');
     } else if (json['error'] != null) {
@@ -1600,7 +1659,7 @@
       if (_typeFactories[type] == null) {
         completer.complete(Response.parse(result));
       } else {
-        completer.complete(createServiceObject(result));
+        completer.complete(createServiceObject(result, returnTypes));
       }
     }
   }
@@ -1619,7 +1678,8 @@
     final Map params = json['params'];
     if (method == 'streamNotify') {
       String streamId = params['streamId'];
-      _getEventController(streamId).add(createServiceObject(params['event']));
+      _getEventController(streamId)
+          .add(createServiceObject(params['event'], const ['Event']));
     } else {
       await _routeRequest(method, params);
     }
@@ -1741,6 +1801,7 @@
   static const String kExtension = 'Extension';
   static const String kTimeline = 'Timeline';
   static const String kLogging = 'Logging';
+  static const String kService = 'Service';
   static const String kStdout = 'Stdout';
   static const String kStderr = 'Stderr';
 }
@@ -2011,15 +2072,16 @@
 
   AllocationProfile._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
-    memoryUsage = createServiceObject(json['memoryUsage']);
+    memoryUsage =
+        createServiceObject(json['memoryUsage'], const ['MemoryUsage']);
     dateLastAccumulatorReset = json['dateLastAccumulatorReset'] is String
         ? int.parse(json['dateLastAccumulatorReset'])
         : json['dateLastAccumulatorReset'];
     dateLastServiceGC = json['dateLastServiceGC'] is String
         ? int.parse(json['dateLastServiceGC'])
         : json['dateLastServiceGC'];
-    members =
-        new List<ClassHeapStats>.from(createServiceObject(json['members']));
+    members = new List<ClassHeapStats>.from(
+        createServiceObject(json['members'], const ['ClassHeapStats']));
   }
 
   @override
@@ -2059,8 +2121,9 @@
   BoundField();
 
   BoundField._fromJson(Map<String, dynamic> json) {
-    decl = createServiceObject(json['decl']);
-    value = createServiceObject(json['value']);
+    decl = createServiceObject(json['decl'], const ['FieldRef']);
+    value =
+        createServiceObject(json['value'], const ['InstanceRef', 'Sentinel']);
   }
 
   Map<String, dynamic> toJson() {
@@ -2108,7 +2171,8 @@
 
   BoundVariable._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    value = createServiceObject(json['value']);
+    value = createServiceObject(
+        json['value'], const ['InstanceRef', 'TypeArgumentsRef', 'Sentinel']);
     declarationTokenPos = json['declarationTokenPos'];
     scopeStartTokenPos = json['scopeStartTokenPos'];
     scopeEndTokenPos = json['scopeEndTokenPos'];
@@ -2166,7 +2230,8 @@
     breakpointNumber = json['breakpointNumber'];
     resolved = json['resolved'];
     isSyntheticAsyncContinuation = json['isSyntheticAsyncContinuation'];
-    location = createServiceObject(json['location']);
+    location = createServiceObject(
+        json['location'], const ['SourceLocation', 'UnresolvedSourceLocation']);
   }
 
   @override
@@ -2284,20 +2349,22 @@
 
   Class._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    error = createServiceObject(json['error']);
+    error = createServiceObject(json['error'], const ['ErrorRef']);
     isAbstract = json['abstract'];
     isConst = json['const'];
-    library = createServiceObject(json['library']);
-    location = createServiceObject(json['location']);
-    superClass = createServiceObject(json['super']);
-    superType = createServiceObject(json['superType']);
-    interfaces =
-        new List<InstanceRef>.from(createServiceObject(json['interfaces']));
-    mixin = createServiceObject(json['mixin']);
-    fields = new List<FieldRef>.from(createServiceObject(json['fields']));
-    functions = new List<FuncRef>.from(createServiceObject(json['functions']));
-    subclasses =
-        new List<ClassRef>.from(createServiceObject(json['subclasses']));
+    library = createServiceObject(json['library'], const ['ObjRef']);
+    location = createServiceObject(json['location'], const ['SourceLocation']);
+    superClass = createServiceObject(json['super'], const ['ClassRef']);
+    superType = createServiceObject(json['superType'], const ['InstanceRef']);
+    interfaces = new List<InstanceRef>.from(
+        createServiceObject(json['interfaces'], const ['InstanceRef']));
+    mixin = createServiceObject(json['mixin'], const ['InstanceRef']);
+    fields = new List<FieldRef>.from(
+        createServiceObject(json['fields'], const ['FieldRef']));
+    functions = new List<FuncRef>.from(
+        createServiceObject(json['functions'], const ['FuncRef']));
+    subclasses = new List<ClassRef>.from(
+        createServiceObject(json['subclasses'], const ['ClassRef']));
   }
 
   @override
@@ -2366,7 +2433,7 @@
     bytesCurrent = json['bytesCurrent'];
     instancesAccumulated = json['instancesAccumulated'];
     instancesCurrent = json['instancesCurrent'];
-    classRef = createServiceObject(json['class']);
+    classRef = createServiceObject(json['class'], const ['ClassRef']);
     new_ = json['new'] == null ? null : new List<int>.from(json['new']);
     old = json['old'] == null ? null : new List<int>.from(json['old']);
     promotedBytes = json['promotedBytes'];
@@ -2403,7 +2470,8 @@
   ClassList();
 
   ClassList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    classes = new List<ClassRef>.from(createServiceObject(json['classes']));
+    classes = new List<ClassRef>.from(
+        createServiceObject(json['classes'], const ['ClassRef']));
   }
 
   @override
@@ -2544,9 +2612,9 @@
 
   Context._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     length = json['length'];
-    parent = createServiceObject(json['parent']);
-    variables =
-        new List<ContextElement>.from(createServiceObject(json['variables']));
+    parent = createServiceObject(json['parent'], const ['Context']);
+    variables = new List<ContextElement>.from(
+        createServiceObject(json['variables'], const ['ContextElement']));
   }
 
   @override
@@ -2579,7 +2647,8 @@
   ContextElement();
 
   ContextElement._fromJson(Map<String, dynamic> json) {
-    value = createServiceObject(json['value']);
+    value =
+        createServiceObject(json['value'], const ['InstanceRef', 'Sentinel']);
   }
 
   Map<String, dynamic> toJson() {
@@ -2657,8 +2726,8 @@
   Error._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
     message = json['message'];
-    exception = createServiceObject(json['exception']);
-    stacktrace = createServiceObject(json['stacktrace']);
+    exception = createServiceObject(json['exception'], const ['InstanceRef']);
+    stacktrace = createServiceObject(json['stacktrace'], const ['InstanceRef']);
   }
 
   @override
@@ -2843,28 +2912,28 @@
 
   Event._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
-    isolate = createServiceObject(json['isolate']);
-    vm = createServiceObject(json['vm']);
+    isolate = createServiceObject(json['isolate'], const ['IsolateRef']);
+    vm = createServiceObject(json['vm'], const ['VMRef']);
     timestamp = json['timestamp'];
-    breakpoint = createServiceObject(json['breakpoint']);
+    breakpoint = createServiceObject(json['breakpoint'], const ['Breakpoint']);
     pauseBreakpoints = json['pauseBreakpoints'] == null
         ? null
-        : new List<Breakpoint>.from(
-            createServiceObject(json['pauseBreakpoints']));
-    topFrame = createServiceObject(json['topFrame']);
-    exception = createServiceObject(json['exception']);
+        : new List<Breakpoint>.from(createServiceObject(
+            json['pauseBreakpoints'], const ['Breakpoint']));
+    topFrame = createServiceObject(json['topFrame'], const ['Frame']);
+    exception = createServiceObject(json['exception'], const ['InstanceRef']);
     bytes = json['bytes'];
-    inspectee = createServiceObject(json['inspectee']);
+    inspectee = createServiceObject(json['inspectee'], const ['InstanceRef']);
     extensionRPC = json['extensionRPC'];
     extensionKind = json['extensionKind'];
     extensionData = ExtensionData.parse(json['extensionData']);
     timelineEvents = json['timelineEvents'] == null
         ? null
-        : new List<TimelineEvent>.from(
-            createServiceObject(json['timelineEvents']));
+        : new List<TimelineEvent>.from(createServiceObject(
+            json['timelineEvents'], const ['TimelineEvent']));
     atAsyncSuspension = json['atAsyncSuspension'];
     status = json['status'];
-    logRecord = createServiceObject(json['logRecord']);
+    logRecord = createServiceObject(json['logRecord'], const ['LogRecord']);
     service = json['service'];
     method = json['method'];
     alias = json['alias'];
@@ -2935,8 +3004,9 @@
 
   FieldRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    owner = createServiceObject(json['owner']);
-    declaredType = createServiceObject(json['declaredType']);
+    owner = createServiceObject(json['owner'], const ['ObjRef']);
+    declaredType =
+        createServiceObject(json['declaredType'], const ['InstanceRef']);
     isConst = json['const'];
     isFinal = json['final'];
     isStatic = json['static'];
@@ -3002,13 +3072,15 @@
 
   Field._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    owner = createServiceObject(json['owner']);
-    declaredType = createServiceObject(json['declaredType']);
+    owner = createServiceObject(json['owner'], const ['ObjRef']);
+    declaredType =
+        createServiceObject(json['declaredType'], const ['InstanceRef']);
     isConst = json['const'];
     isFinal = json['final'];
     isStatic = json['static'];
-    staticValue = createServiceObject(json['staticValue']);
-    location = createServiceObject(json['location']);
+    staticValue =
+        createServiceObject(json['staticValue'], const ['InstanceRef']);
+    location = createServiceObject(json['location'], const ['SourceLocation']);
   }
 
   @override
@@ -3090,7 +3162,8 @@
   FlagList();
 
   FlagList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    flags = new List<Flag>.from(createServiceObject(json['flags']));
+    flags =
+        new List<Flag>.from(createServiceObject(json['flags'], const ['Flag']));
   }
 
   @override
@@ -3132,12 +3205,13 @@
 
   Frame._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     index = json['index'];
-    function = createServiceObject(json['function']);
-    code = createServiceObject(json['code']);
-    location = createServiceObject(json['location']);
+    function = createServiceObject(json['function'], const ['FuncRef']);
+    code = createServiceObject(json['code'], const ['CodeRef']);
+    location = createServiceObject(json['location'], const ['SourceLocation']);
     vars = json['vars'] == null
         ? null
-        : new List<BoundVariable>.from(createServiceObject(json['vars']));
+        : new List<BoundVariable>.from(
+            createServiceObject(json['vars'], const ['BoundVariable']));
     kind = json['kind'];
   }
 
@@ -3182,7 +3256,8 @@
 
   FuncRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    owner = createServiceObject(json['owner']);
+    owner = createServiceObject(
+        json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']);
     isStatic = json['static'];
     isConst = json['const'];
   }
@@ -3234,9 +3309,10 @@
 
   Func._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    owner = createServiceObject(json['owner']);
-    location = createServiceObject(json['location']);
-    code = createServiceObject(json['code']);
+    owner = createServiceObject(
+        json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']);
+    location = createServiceObject(json['location'], const ['SourceLocation']);
+    code = createServiceObject(json['code'], const ['CodeRef']);
   }
 
   @override
@@ -3351,14 +3427,15 @@
 
   InstanceRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
-    classRef = createServiceObject(json['class']);
+    classRef = createServiceObject(json['class'], const ['ClassRef']);
     valueAsString = json['valueAsString'];
     valueAsStringIsTruncated = json['valueAsStringIsTruncated'] ?? false;
     length = json['length'];
     name = json['name'];
-    typeClass = createServiceObject(json['typeClass']);
-    parameterizedClass = createServiceObject(json['parameterizedClass']);
-    pattern = createServiceObject(json['pattern']);
+    typeClass = createServiceObject(json['typeClass'], const ['ClassRef']);
+    parameterizedClass =
+        createServiceObject(json['parameterizedClass'], const ['ClassRef']);
+    pattern = createServiceObject(json['pattern'], const ['InstanceRef']);
   }
 
   @override
@@ -3396,6 +3473,10 @@
   /// What kind of instance is this?
   /*InstanceKind*/ String kind;
 
+  /// Instance references always include their class.
+  @override
+  ClassRef classRef;
+
   /// The value of this instance as a string.
   ///
   /// Provided for the instance kinds:
@@ -3553,13 +3634,14 @@
   @optional
   FuncRef closureFunction;
 
-  /// TODO(devoncarew): this can return an InstanceRef
-  ///
   /// The context associated with a Closure instance.
   ///
   /// Provided for instance kinds:
-  /// - Closure@Context closureContext [optional]; The referent of a
-  /// MirrorReference instance.
+  ///  - Closure
+  @optional
+  ContextRef closureContext;
+
+  /// The referent of a MirrorReference instance.
   ///
   /// Provided for instance kinds:
   ///  - MirrorReference
@@ -3642,36 +3724,47 @@
 
   Instance._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
+    classRef = createServiceObject(json['class'], const ['ClassRef']);
     valueAsString = json['valueAsString'];
     valueAsStringIsTruncated = json['valueAsStringIsTruncated'] ?? false;
     length = json['length'];
     offset = json['offset'];
     count = json['count'];
     name = json['name'];
-    typeClass = createServiceObject(json['typeClass']);
-    parameterizedClass = createServiceObject(json['parameterizedClass']);
+    typeClass = createServiceObject(json['typeClass'], const ['ClassRef']);
+    parameterizedClass =
+        createServiceObject(json['parameterizedClass'], const ['ClassRef']);
     fields = json['fields'] == null
         ? null
-        : new List<BoundField>.from(createServiceObject(json['fields']));
+        : new List<BoundField>.from(
+            createServiceObject(json['fields'], const ['BoundField']));
     elements = json['elements'] == null
         ? null
-        : new List<dynamic>.from(createServiceObject(json['elements']));
+        : new List<dynamic>.from(
+            createServiceObject(json['elements'], const ['dynamic']));
     associations = json['associations'] == null
         ? null
         : new List<MapAssociation>.from(
             _createSpecificObject(json['associations'], MapAssociation.parse));
     bytes = json['bytes'];
-    closureFunction = createServiceObject(json['closureFunction']);
-    mirrorReferent = createServiceObject(json['mirrorReferent']);
+    closureFunction =
+        createServiceObject(json['closureFunction'], const ['FuncRef']);
+    closureContext =
+        createServiceObject(json['closureContext'], const ['ContextRef']);
+    mirrorReferent =
+        createServiceObject(json['mirrorReferent'], const ['InstanceRef']);
     pattern = json['pattern'];
     isCaseSensitive = json['isCaseSensitive'];
     isMultiLine = json['isMultiLine'];
-    propertyKey = createServiceObject(json['propertyKey']);
-    propertyValue = createServiceObject(json['propertyValue']);
-    typeArguments = createServiceObject(json['typeArguments']);
+    propertyKey =
+        createServiceObject(json['propertyKey'], const ['InstanceRef']);
+    propertyValue =
+        createServiceObject(json['propertyValue'], const ['InstanceRef']);
+    typeArguments =
+        createServiceObject(json['typeArguments'], const ['TypeArgumentsRef']);
     parameterIndex = json['parameterIndex'];
-    targetType = createServiceObject(json['targetType']);
-    bound = createServiceObject(json['bound']);
+    targetType = createServiceObject(json['targetType'], const ['InstanceRef']);
+    bound = createServiceObject(json['bound'], const ['InstanceRef']);
   }
 
   @override
@@ -3680,6 +3773,7 @@
     json['type'] = 'Instance';
     json.addAll({
       'kind': kind,
+      'class': classRef.toJson(),
     });
     _setIfNotNull(json, 'valueAsString', valueAsString);
     _setIfNotNull(
@@ -3697,6 +3791,7 @@
         json, 'associations', associations?.map((f) => f?.toJson())?.toList());
     _setIfNotNull(json, 'bytes', bytes);
     _setIfNotNull(json, 'closureFunction', closureFunction?.toJson());
+    _setIfNotNull(json, 'closureContext', closureContext?.toJson());
     _setIfNotNull(json, 'mirrorReferent', mirrorReferent?.toJson());
     _setIfNotNull(json, 'pattern', pattern);
     _setIfNotNull(json, 'isCaseSensitive', isCaseSensitive);
@@ -3714,7 +3809,8 @@
 
   operator ==(other) => other is Instance && id == other.id;
 
-  String toString() => '[Instance type: ${type}, id: ${id}, kind: ${kind}]';
+  String toString() => '[Instance ' //
+      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}]';
 }
 
 /// `IsolateRef` is a reference to an `Isolate` object.
@@ -3827,13 +3923,13 @@
     runnable = json['runnable'];
     livePorts = json['livePorts'];
     pauseOnExit = json['pauseOnExit'];
-    pauseEvent = createServiceObject(json['pauseEvent']);
-    rootLib = createServiceObject(json['rootLib']);
-    libraries =
-        new List<LibraryRef>.from(createServiceObject(json['libraries']));
-    breakpoints =
-        new List<Breakpoint>.from(createServiceObject(json['breakpoints']));
-    error = createServiceObject(json['error']);
+    pauseEvent = createServiceObject(json['pauseEvent'], const ['Event']);
+    rootLib = createServiceObject(json['rootLib'], const ['LibraryRef']);
+    libraries = new List<LibraryRef>.from(
+        createServiceObject(json['libraries'], const ['LibraryRef']));
+    breakpoints = new List<Breakpoint>.from(
+        createServiceObject(json['breakpoints'], const ['Breakpoint']));
+    error = createServiceObject(json['error'], const ['Error']);
     exceptionPauseMode = json['exceptionPauseMode'];
     extensionRPCs = json['extensionRPCs'] == null
         ? null
@@ -3886,8 +3982,8 @@
 
   InstanceSet._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     totalCount = json['totalCount'];
-    instances = new List<ObjRef>.from(
-        createServiceObject(json['instances'] ?? json['samples']));
+    instances = new List<ObjRef>.from(createServiceObject(
+        json['instances'] ?? json['samples'], const ['ObjRef']));
   }
 
   @override
@@ -3981,10 +4077,14 @@
     debuggable = json['debuggable'];
     dependencies = new List<LibraryDependency>.from(
         _createSpecificObject(json['dependencies'], LibraryDependency.parse));
-    scripts = new List<ScriptRef>.from(createServiceObject(json['scripts']));
-    variables = new List<FieldRef>.from(createServiceObject(json['variables']));
-    functions = new List<FuncRef>.from(createServiceObject(json['functions']));
-    classes = new List<ClassRef>.from(createServiceObject(json['classes']));
+    scripts = new List<ScriptRef>.from(
+        createServiceObject(json['scripts'], const ['ScriptRef']));
+    variables = new List<FieldRef>.from(
+        createServiceObject(json['variables'], const ['FieldRef']));
+    functions = new List<FuncRef>.from(
+        createServiceObject(json['functions'], const ['FuncRef']));
+    classes = new List<ClassRef>.from(
+        createServiceObject(json['classes'], const ['ClassRef']));
   }
 
   @override
@@ -4034,7 +4134,7 @@
     isImport = json['isImport'];
     isDeferred = json['isDeferred'];
     prefix = json['prefix'];
-    target = createServiceObject(json['target']);
+    target = createServiceObject(json['target'], const ['LibraryRef']);
   }
 
   Map<String, dynamic> toJson() {
@@ -4087,14 +4187,14 @@
   LogRecord();
 
   LogRecord._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    message = createServiceObject(json['message']);
+    message = createServiceObject(json['message'], const ['InstanceRef']);
     time = json['time'];
     level = json['level'];
     sequenceNumber = json['sequenceNumber'];
-    loggerName = createServiceObject(json['loggerName']);
-    zone = createServiceObject(json['zone']);
-    error = createServiceObject(json['error']);
-    stackTrace = createServiceObject(json['stackTrace']);
+    loggerName = createServiceObject(json['loggerName'], const ['InstanceRef']);
+    zone = createServiceObject(json['zone'], const ['InstanceRef']);
+    error = createServiceObject(json['error'], const ['InstanceRef']);
+    stackTrace = createServiceObject(json['stackTrace'], const ['InstanceRef']);
   }
 
   @override
@@ -4130,8 +4230,9 @@
   MapAssociation();
 
   MapAssociation._fromJson(Map<String, dynamic> json) {
-    key = createServiceObject(json['key']);
-    value = createServiceObject(json['value']);
+    key = createServiceObject(json['key'], const ['InstanceRef', 'Sentinel']);
+    value =
+        createServiceObject(json['value'], const ['InstanceRef', 'Sentinel']);
   }
 
   Map<String, dynamic> toJson() {
@@ -4146,7 +4247,7 @@
   String toString() => '[MapAssociation key: ${key}, value: ${value}]';
 }
 
-/// An `MemoryUsage` object provides heap usage information for a specific
+/// A `MemoryUsage` object provides heap usage information for a specific
 /// isolate at a given point in time.
 class MemoryUsage extends Response {
   static MemoryUsage parse(Map<String, dynamic> json) =>
@@ -4228,8 +4329,8 @@
     name = json['name'];
     messageObjectId = json['messageObjectId'];
     size = json['size'];
-    handler = createServiceObject(json['handler']);
-    location = createServiceObject(json['location']);
+    handler = createServiceObject(json['handler'], const ['FuncRef']);
+    location = createServiceObject(json['location'], const ['SourceLocation']);
   }
 
   @override
@@ -4257,14 +4358,23 @@
   static NullValRef parse(Map<String, dynamic> json) =>
       json == null ? null : new NullValRef._fromJson(json);
 
+  /// Always 'null'.
+  @override
+  String valueAsString;
+
   NullValRef();
 
-  NullValRef._fromJson(Map<String, dynamic> json) : super._fromJson(json);
+  NullValRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
+    valueAsString = json['valueAsString'];
+  }
 
   @override
   Map<String, dynamic> toJson() {
     var json = super.toJson();
     json['type'] = '@Null';
+    json.addAll({
+      'valueAsString': valueAsString,
+    });
     return json;
   }
 
@@ -4273,7 +4383,8 @@
   operator ==(other) => other is NullValRef && id == other.id;
 
   String toString() => '[NullValRef ' //
-      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}]';
+      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}, ' //
+      'valueAsString: ${valueAsString}]';
 }
 
 /// A `NullVal` object represents the Dart language value null.
@@ -4281,14 +4392,23 @@
   static NullVal parse(Map<String, dynamic> json) =>
       json == null ? null : new NullVal._fromJson(json);
 
+  /// Always 'null'.
+  @override
+  String valueAsString;
+
   NullVal();
 
-  NullVal._fromJson(Map<String, dynamic> json) : super._fromJson(json);
+  NullVal._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
+    valueAsString = json['valueAsString'];
+  }
 
   @override
   Map<String, dynamic> toJson() {
     var json = super.toJson();
     json['type'] = 'Null';
+    json.addAll({
+      'valueAsString': valueAsString,
+    });
     return json;
   }
 
@@ -4296,7 +4416,9 @@
 
   operator ==(other) => other is NullVal && id == other.id;
 
-  String toString() => '[NullVal type: ${type}, id: ${id}, kind: ${kind}]';
+  String toString() => '[NullVal ' //
+      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}, ' //
+      'valueAsString: ${valueAsString}]';
 }
 
 /// `ObjRef` is a reference to a `Obj`.
@@ -4382,7 +4504,7 @@
   Obj._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     id = json['id'];
     fixedId = json['fixedId'];
-    classRef = createServiceObject(json['class']);
+    classRef = createServiceObject(json['class'], const ['ClassRef']);
     size = json['size'];
   }
 
@@ -4587,7 +4709,7 @@
 
   Script._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     uri = json['uri'];
-    library = createServiceObject(json['library']);
+    library = createServiceObject(json['library'], const ['LibraryRef']);
     lineOffset = json['lineOffset'];
     columnOffset = json['columnOffset'];
     source = json['source'];
@@ -4630,7 +4752,8 @@
   ScriptList();
 
   ScriptList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    scripts = new List<ScriptRef>.from(createServiceObject(json['scripts']));
+    scripts = new List<ScriptRef>.from(
+        createServiceObject(json['scripts'], const ['ScriptRef']));
   }
 
   @override
@@ -4665,7 +4788,7 @@
   SourceLocation();
 
   SourceLocation._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    script = createServiceObject(json['script']);
+    script = createServiceObject(json['script'], const ['ScriptRef']);
     tokenPos = json['tokenPos'];
     endTokenPos = json['endTokenPos'];
   }
@@ -4710,7 +4833,8 @@
   SourceReport._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     ranges = new List<SourceReportRange>.from(
         _createSpecificObject(json['ranges'], SourceReportRange.parse));
-    scripts = new List<ScriptRef>.from(createServiceObject(json['scripts']));
+    scripts = new List<ScriptRef>.from(
+        createServiceObject(json['scripts'], const ['ScriptRef']));
   }
 
   @override
@@ -4812,7 +4936,7 @@
     startPos = json['startPos'];
     endPos = json['endPos'];
     compiled = json['compiled'];
-    error = createServiceObject(json['error']);
+    error = createServiceObject(json['error'], const ['ErrorRef']);
     coverage =
         _createSpecificObject(json['coverage'], SourceReportCoverage.parse);
     possibleBreakpoints = json['possibleBreakpoints'] == null
@@ -4857,14 +4981,18 @@
   Stack();
 
   Stack._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    frames = new List<Frame>.from(createServiceObject(json['frames']));
+    frames = new List<Frame>.from(
+        createServiceObject(json['frames'], const ['Frame']));
     asyncCausalFrames = json['asyncCausalFrames'] == null
         ? null
-        : new List<Frame>.from(createServiceObject(json['asyncCausalFrames']));
+        : new List<Frame>.from(
+            createServiceObject(json['asyncCausalFrames'], const ['Frame']));
     awaiterFrames = json['awaiterFrames'] == null
         ? null
-        : new List<Frame>.from(createServiceObject(json['awaiterFrames']));
-    messages = new List<Message>.from(createServiceObject(json['messages']));
+        : new List<Frame>.from(
+            createServiceObject(json['awaiterFrames'], const ['Frame']));
+    messages = new List<Message>.from(
+        createServiceObject(json['messages'], const ['Message']));
   }
 
   @override
@@ -4922,8 +5050,8 @@
   Timeline();
 
   Timeline._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    traceEvents =
-        new List<TimelineEvent>.from(createServiceObject(json['traceEvents']));
+    traceEvents = new List<TimelineEvent>.from(
+        createServiceObject(json['traceEvents'], const ['TimelineEvent']));
     timeOriginMicros = json['timeOriginMicros'];
     timeExtentMicros = json['timeExtentMicros'];
   }
@@ -5081,7 +5209,8 @@
 
   TypeArguments._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    types = new List<InstanceRef>.from(createServiceObject(json['types']));
+    types = new List<InstanceRef>.from(
+        createServiceObject(json['types'], const ['InstanceRef']));
   }
 
   @override
@@ -5145,7 +5274,7 @@
 
   UnresolvedSourceLocation._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
-    script = createServiceObject(json['script']);
+    script = createServiceObject(json['script'], const ['ScriptRef']);
     scriptUri = json['scriptUri'];
     tokenPos = json['tokenPos'];
     line = json['line'];
@@ -5269,7 +5398,8 @@
     version = json['version'];
     pid = json['pid'];
     startTime = json['startTime'];
-    isolates = new List<IsolateRef>.from(createServiceObject(json['isolates']));
+    isolates = new List<IsolateRef>.from(
+        createServiceObject(json['isolates'], const ['IsolateRef']));
   }
 
   @override
@@ -5382,7 +5512,7 @@
     kind = json['kind'];
     inclusiveTicks = json['inclusiveTicks'];
     exclusiveTicks = json['exclusiveTicks'];
-    code = createServiceObject(json['code']);
+    code = createServiceObject(json['code'], const ['CodeRef']);
   }
 
   Map<String, dynamic> toJson() {
@@ -5421,7 +5551,7 @@
     kind = json['kind'];
     inclusiveTicks = json['inclusiveTicks'];
     exclusiveTicks = json['exclusiveTicks'];
-    function = createServiceObject(json['function']);
+    function = createServiceObject(json['function'], const ['FuncRef']);
     codes = new List<int>.from(json['codes']);
   }
 
diff --git a/vm_service_lib/pubspec.yaml b/vm_service_lib/pubspec.yaml
index fe2d6e7..a02f617 100644
--- a/vm_service_lib/pubspec.yaml
+++ b/vm_service_lib/pubspec.yaml
@@ -1,6 +1,6 @@
 name: vm_service_lib
 description: A library to access the VM Service API.
-version: 3.21.0
+version: 3.22.0
 
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/vm_service_drivers
diff --git a/vm_service_lib/tool/common/src_gen_common.dart b/vm_service_lib/tool/common/src_gen_common.dart
index 8eeed99..0a47d1c 100644
--- a/vm_service_lib/tool/common/src_gen_common.dart
+++ b/vm_service_lib/tool/common/src_gen_common.dart
@@ -22,8 +22,10 @@
 bool isH1(Node node) => node is Element && node.tag == 'h1';
 bool isH3(Node node) => node is Element && node.tag == 'h3';
 bool isHeader(Node node) => node is Element && node.tag.startsWith('h');
-String textForElement(Node node) => (((node as Element).children.first) as Text).text;
-String textForCode(Node node) => textForElement((node as Element).children.first);
+String textForElement(Node node) =>
+    (((node as Element).children.first) as Text).text;
+String textForCode(Node node) =>
+    textForElement((node as Element).children.first);
 
 /// foo ==> Foo
 String titleCase(String str) =>
diff --git a/vm_service_lib/tool/dart/generate_dart.dart b/vm_service_lib/tool/dart/generate_dart.dart
index 79d917f..515331f 100644
--- a/vm_service_lib/tool/dart/generate_dart.dart
+++ b/vm_service_lib/tool/dart/generate_dart.dart
@@ -31,6 +31,9 @@
   return typeName;
 }
 
+String _typeRefListToString(List<TypeRef> types) =>
+    'const [' + types.map((e) => "'" + e.name + "'").join(',') + ']';
+
 final String _headerCode = r'''
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -144,7 +147,7 @@
       String streamId = map['params']['streamId'];
       Map event = map['params']['event'];
       event['_data'] = data;
-      _getEventController(streamId).add(createServiceObject(event));
+      _getEventController(streamId).add(createServiceObject(event, const ['Event']));
     }
   }
 
@@ -178,7 +181,7 @@
   void _processResponse(Map<String, dynamic> json) {
     Completer completer = _completers.remove(json['id']);
     String methodName = _methodCalls.remove(json['id']);
-
+    List<String> returnTypes = _methodReturnTypes[methodName];
     if (completer == null) {
       _log.severe('unmatched request response: ${jsonEncode(json)}');
     } else if (json['error'] != null) {
@@ -189,7 +192,7 @@
       if (_typeFactories[type] == null) {
         completer.complete(Response.parse(result));
       } else {
-        completer.complete(createServiceObject(result));
+        completer.complete(createServiceObject(result, returnTypes));
       }
     }
   }
@@ -208,7 +211,7 @@
     final Map params = json['params'];
     if (method == 'streamNotify') {
       String streamId = params['streamId'];
-      _getEventController(streamId).add(createServiceObject(params['event']));
+      _getEventController(streamId).add(createServiceObject(params['event'], const ['Event']));
     } else {
       await _routeRequest(method, params);
     }
@@ -387,7 +390,7 @@
     }
 
     for (Type type in types) {
-      type.removeDuplicateFieldDefs();
+      type.calculateFieldOverrides();
     }
 
     Method streamListenMethod =
@@ -454,13 +457,20 @@
 /// This is useful for handling the results of the Stdout or Stderr events.
 String decodeBase64(String str) => utf8.decode(base64.decode(str));
 
-Object createServiceObject(dynamic json) {
+// Returns true if a response is the Dart `null` instance.
+bool _isNullInstance(Map json) => ((json['type'] == '@Instance') &&
+                                  (json['kind'] == 'Null'));
+
+Object createServiceObject(dynamic json, List<String> expectedTypes) {
   if (json == null) return null;
 
   if (json is List) {
-    return json.map((e) => createServiceObject(e)).toList();
+    return json.map((e) => createServiceObject(e, expectedTypes)).toList();
   } else if (json is Map) {
     String type = json['type'];
+    if (_isNullInstance(json) && (!expectedTypes.contains(type))) {
+      return null;
+    }
     if (_typeFactories[type] == null) {
       return null;
     } else {
@@ -499,13 +509,21 @@
 
 ''');
     gen.writeln();
-    gen.write('Map<String, Function> _typeFactories = {');
+    gen.writeln('Map<String, Function> _typeFactories = {');
     types.forEach((Type type) {
       gen.writeln("'${type.rawName}': ${type.publicName}.parse,");
     });
     gen.writeln('};');
     gen.writeln();
 
+    gen.writeln('Map<String, List<String>> _methodReturnTypes = {');
+    methods.forEach((Method method) {
+      String returnTypes = _typeRefListToString(method.returnType.types);
+      gen.writeln("'${method.name}' : $returnTypes,");
+    });
+    gen.writeln('};');
+    gen.writeln();
+
     // The service interface, both servers and clients implement this.
     gen.writeStatement('''
 /// A class representation of the Dart VM Service Protocol.
@@ -1334,7 +1352,7 @@
         if (name == 'AllocationProfile' && field.type.name == 'int') {
           gen.write(
               "${field.generatableName} = json['${field.name}'] is String ? "
-                  "int.parse(json['${field.name}']) : json['${field.name}']");
+              "int.parse(json['${field.name}']) : json['${field.name}']");
         } else {
           gen.write("${field.generatableName} = json['${field.name}']");
         }
@@ -1387,6 +1405,7 @@
             "((dynamic list) => new List<int>.from(list)));");
       } else if (field.type.isArray) {
         TypeRef fieldType = field.type.types.first;
+        String typesList = _typeRefListToString(field.type.types);
         String ref = "json['${field.name}']";
         if (field.optional) {
           if (fieldType.isListTypeSimple) {
@@ -1394,7 +1413,7 @@
                 "new List<${fieldType.listTypeArg}>.from($ref);");
           } else {
             gen.writeln("${field.generatableName} = $ref == null ? null : "
-                "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref));");
+                "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
           }
         } else {
           if (fieldType.isListTypeSimple) {
@@ -1412,16 +1431,17 @@
             // field named 'samples' instead of 'instances'.
             if (name == 'InstanceSet') {
               gen.writeln("${field.generatableName} = "
-                  "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref ?? json['samples']));");
+                  "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref ?? json['samples'], $typesList));");
             } else {
               gen.writeln("${field.generatableName} = "
-                  "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref));");
+                  "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
             }
           }
         }
       } else {
+        String typesList = _typeRefListToString(field.type.types);
         gen.writeln("${field.generatableName} = "
-            "createServiceObject(json['${field.name}']);");
+            "createServiceObject(json['${field.name}'], $typesList);");
       }
     });
     if (fields.isNotEmpty) {
@@ -1599,13 +1619,12 @@
     new TypeParser(token).parseInto(this);
   }
 
-  void removeDuplicateFieldDefs() {
+  void calculateFieldOverrides() {
     for (TypeField field in fields.toList()) {
       if (superName == null) continue;
 
       if (getSuper().hasField(field.name)) {
-        print('Removing duplicate field def: ${name}.${field.name}.');
-        fields.remove(field);
+        field.setOverrides();
       }
     }
   }
@@ -1633,9 +1652,14 @@
   String name;
   bool optional = false;
   String defaultValue;
+  bool overrides = false;
 
   TypeField(this.parent, this._docs);
 
+  void setOverrides() {
+    overrides = true;
+  }
+
   String get docs {
     String str = _docs == null ? '' : _docs;
     if (type.isMultipleReturns) {
@@ -1653,6 +1677,7 @@
   void generate(DartGenerator gen) {
     if (docs.isNotEmpty) gen.writeDocs(docs);
     if (optional) gen.write('@optional ');
+    if (overrides) gen.write('@override ');
     String typeName =
         api.isEnumName(type.name) ? '/*${type.name}*/ String' : type.name;
     gen.writeStatement('${typeName} ${generatableName};');
@@ -1749,7 +1774,7 @@
   TextOutputVisitor();
 
   bool visitElementBefore(Element element) {
-    if (element.tag == 'em') {
+    if (element.tag == 'em' || element.tag == 'code') {
       buf.write('`');
       _em = true;
     } else if (element.tag == 'p') {
@@ -1759,9 +1784,6 @@
       _blockquote = true;
     } else if (element.tag == 'a') {
       _href = true;
-    } else {
-      print('unknown tag: ${element.tag}');
-      buf.write(renderToHtml([element]));
     }
 
     return true;
@@ -1783,16 +1805,19 @@
   }
 
   void visitElementAfter(Element element) {
-    if (element.tag == 'p') {
+    if (element.tag == 'em' || element.tag == 'code') {
+      buf.write('`');
+      _em = false;
+    } else if (element.tag == 'p') {
       buf.write('\n\n');
-    } else if (element.tag == 'a') {
-      _href = false;
     } else if (element.tag == 'blockquote') {
       //buf.write('```\n');
       _blockquote = false;
-    } else if (element.tag == 'em') {
-      buf.write('`');
-      _em = false;
+    } else if (element.tag == 'a') {
+      _href = false;
+    } else {
+      print('             </${element.tag}>');
+      buf.write(renderToHtml([element]));
     }
   }
 
diff --git a/vm_service_lib/tool/generate.dart b/vm_service_lib/tool/generate.dart
index e90b321..fd5b92b 100644
--- a/vm_service_lib/tool/generate.dart
+++ b/vm_service_lib/tool/generate.dart
@@ -24,7 +24,8 @@
   var document = new Document();
   StringBuffer buf = new StringBuffer(file.readAsStringSync());
   buf.writeln();
-  buf.write(new File(join(appDirPath, 'service_undocumented.md')).readAsStringSync());
+  buf.write(
+      new File(join(appDirPath, 'service_undocumented.md')).readAsStringSync());
   var nodes = document.parseLines(buf.toString().split('\n'));
   print('Parsed ${file.path}.');
   print('Service protocol version ${ApiParseUtil.parseVersionString(nodes)}.');
@@ -115,7 +116,8 @@
       Version v = new Version.parse(line.substring(pattern.length));
       String pre = v.preRelease.isEmpty ? null : v.preRelease.join('-');
       String build = v.build.isEmpty ? null : v.build.join('+');
-      v = new Version(version.major, version.minor, v.patch, pre: pre, build: build);
+      v = new Version(version.major, version.minor, v.patch,
+          pre: pre, build: build);
       return '${pattern}${v.toString()}';
     } else {
       return line;
@@ -133,6 +135,9 @@
 
   File file = new File('CHANGELOG.md');
   String text = file.readAsStringSync();
-  bool containsReleaseNotes = text.split('\n').any((line) => line.startsWith(check));
-  if (!containsReleaseNotes) throw '`${check}` not found in the CHANGELOG.md file';
+  bool containsReleaseNotes =
+      text.split('\n').any((line) => line.startsWith(check));
+  if (!containsReleaseNotes) {
+    throw '`${check}` not found in the CHANGELOG.md file';
+  }
 }
diff --git a/vm_service_lib/tool/java/generate_java.dart b/vm_service_lib/tool/java/generate_java.dart
index 135427b..b4c0b3e 100644
--- a/vm_service_lib/tool/java/generate_java.dart
+++ b/vm_service_lib/tool/java/generate_java.dart
@@ -319,6 +319,10 @@
     // or Enum values.
     _mergeTypes();
     _mergeEnums();
+
+    for (Type type in types) {
+      type.calculateFieldOverrides();
+    }
   }
 
   void setDefaultValue(String typeName, String propertyName) {
@@ -757,15 +761,6 @@
 
   String toString() => buf.toString().trim();
 
-  void visitElementAfter(Element element) {
-    if (element.tag == 'p') {
-      buf.write('\n\n');
-    } else if (element.tag == 'em') {
-      buf.write(']');
-      _inRef = false;
-    }
-  }
-
   bool visitElementBefore(Element element) {
     if (element.tag == 'em') {
       buf.write('[');
@@ -774,6 +769,8 @@
       // Nothing to do.
     } else if (element.tag == 'a') {
       // Nothing to do - we're not writing out <a> refs (they won't resolve).
+    } else if (element.tag == 'code') {
+      buf.write(renderToHtml([element]));
     } else {
       print('unknown tag: ${element.tag}');
       buf.write(renderToHtml([element]));
@@ -788,6 +785,15 @@
     buf.write(t);
   }
 
+  void visitElementAfter(Element element) {
+    if (element.tag == 'em') {
+      buf.write(']');
+      _inRef = false;
+    } else if (element.tag == 'p') {
+      buf.write('\n\n');
+    }
+  }
+
   static String printText(Node node) {
     TextOutputVisitor visitor = new TextOutputVisitor();
     node.accept(visitor);
@@ -870,6 +876,18 @@
         writer.addLine('super(json);');
       });
 
+      if (name == 'InstanceRef' || name == 'Instance') {
+        writer.addMethod(
+          'isNull',
+          [],
+          (StatementWriter writer) {
+            writer.addLine('return getKind() == InstanceKind.Null;');
+          },
+          returnType: 'boolean',
+          javadoc: 'Returns whether this instance represents null.',
+        );
+      }
+
       for (var field in fields) {
         field.generateAccessor(writer);
       }
@@ -893,9 +911,24 @@
 
   Type getSuper() => superName == null ? null : api.getType(superName);
 
+  bool hasField(String name) {
+    if (fields.any((field) => field.name == name)) return true;
+    return getSuper()?.hasField(name) ?? false;
+  }
+
   void _parse(Token token) {
     new TypeParser(token).parseInto(this);
   }
+
+  void calculateFieldOverrides() {
+    for (TypeField field in fields.toList()) {
+      if (superName == null) continue;
+
+      if (getSuper().hasField(field.name)) {
+        field.setOverrides();
+      }
+    }
+  }
 }
 
 // @Instance|@Error|Sentinel evaluate(
@@ -918,9 +951,14 @@
   String name;
   bool optional = false;
   String defaultValue;
+  bool overrides = false;
 
   TypeField(this.parent, this._docs);
 
+  void setOverrides() {
+    overrides = true;
+  }
+
   String get accessorName {
     var remappedName = _nameRemap[name];
     if (remappedName != null) {
@@ -967,12 +1005,22 @@
         returnType = 'long';
       }
 
-      writer.addMethod(accessorName, [], (StatementWriter writer) {
-        type.valueType.generateAccessStatements(writer, name,
+      writer.addMethod(
+        accessorName,
+        [],
+        (StatementWriter writer) {
+          type.valueType.generateAccessStatements(
+            writer,
+            name,
             canBeSentinel: type.isValueAndSentinel,
             defaultValue: defaultValue,
-            optional: optional);
-      }, javadoc: docs, returnType: returnType);
+            optional: optional,
+          );
+        },
+        javadoc: docs,
+        returnType: returnType,
+        isOverride: overrides,
+      );
     }
   }
 }
@@ -1059,8 +1107,13 @@
 
   Type get type => api.types.firstWhere((t) => t.name == name);
 
-  void generateAccessStatements(StatementWriter writer, String propertyName,
-      {bool canBeSentinel = false, String defaultValue, bool optional = false}) {
+  void generateAccessStatements(
+    StatementWriter writer,
+    String propertyName, {
+    bool canBeSentinel = false,
+    String defaultValue,
+    bool optional = false,
+  }) {
     if (name == 'boolean') {
       if (isArray) {
         print('skipped accessor body for $propertyName');
@@ -1159,13 +1212,26 @@
           writer.addLine('final JsonElement elem = json.get("$propertyName");');
           writer.addLine('if (!elem.isJsonObject()) return null;');
           writer.addLine('final JsonObject child = elem.getAsJsonObject();');
-          writer.addLine('final String type = child.get("type").getAsString();');
+          writer
+              .addLine('final String type = child.get("type").getAsString();');
           writer.addLine('if ("Sentinel".equals(type)) return null;');
           writer.addLine('return new $name(child);');
         } else {
           if (optional) {
-            writer.addLine('return json.get("$propertyName") == null ? '
-                'null : new $name((JsonObject) json.get("$propertyName"));');
+            writer.addLine(
+                'JsonObject obj = (JsonObject) json.get("$propertyName");');
+            writer.addLine('if (obj == null) return null;');
+            if ((name != 'InstanceRef') && (name != 'Instance')) {
+              writer.addLine(
+                  'final String type = json.get("type").getAsString();');
+              writer.addLine(
+                  'if ("Instance".equals(type) || "@Instance".equals(type)) {');
+              writer.addLine(
+                  '  final String kind = json.get("kind").getAsString();');
+              writer.addLine('  if ("Null".equals(kind)) return null;');
+              writer.addLine('}');
+            }
+            writer.addLine('return new $name(obj);');
           } else {
             writer.addLine(
                 'return new $name((JsonObject) json.get("$propertyName"));');
diff --git a/vm_service_lib/tool/service.md b/vm_service_lib/tool/service.md
index 62d3c8a..92fb0d3 100644
--- a/vm_service_lib/tool/service.md
+++ b/vm_service_lib/tool/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.21
+# Dart VM Service Protocol 3.22
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.21_ of the Dart VM Service Protocol. This
+This document describes of _version 3.22_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -47,6 +47,7 @@
   - [invoke](#invoke)
   - [pause](#pause)
   - [kill](#kill)
+  - [registerService](#registerService)
   - [reloadSources](#reloadsources)
   - [removeBreakpoint](#removebreakpoint)
   - [resume](#resume)
@@ -878,6 +879,21 @@
 
 See [Success](#success).
 
+### registerService
+
+```
+Success registerService(string service, string alias)
+```
+
+Registers a service that can be invoked by other VM service clients, where
+`service` is the name of the service to advertise and `alias` is an alternative
+name for the registered service.
+
+Requests made to the new service will be forwarded to the client which originally
+registered the service.
+
+See [Success](#success).
+
 ### reloadSources
 
 ```
@@ -1071,6 +1087,7 @@
 Extension | Extension
 Timeline | TimelineEvents
 Logging | Logging
+Service | ServiceRegistered, ServiceUnregistered
 
 Additionally, some embedders provide the _Stdout_ and _Stderr_
 streams.  These streams allow the client to subscribe to writes to
@@ -1599,6 +1616,26 @@
   //
   // This is provided for the Logging event.
   LogRecord logRecord [optional];
+
+  // The service identifier.
+  //
+  // This is provided for the event kinds:
+  //   ServiceRegistered
+  //   ServiceUnregistered
+  String service [optional];
+
+  // The RPC method that should be used to invoke the service.
+  //
+  // This is provided for the event kinds:
+  //   ServiceRegistered
+  //   ServiceUnregistered
+  String method [optional];
+
+  // The alias of the registered service.
+  //
+  // This is provided for the event kinds:
+  //   ServiceRegistered
+  String alias [optional];
 }
 ```
 
@@ -1684,6 +1721,14 @@
 
   // Event from dart:developer.log.
   Logging
+
+   // Notification that a Service has been registered into the Service Protocol
+  // from another client.
+  ServiceRegistered,
+
+  // Notification that a Service has been removed from the Service Protocol
+  // from another client.
+  ServiceUnregistered
 }
 ```
 
@@ -2086,13 +2131,11 @@
   //   Closure
   @Function closureFunction [optional];
 
-  // TODO(devoncarew): this can return an InstanceRef
-  //
   // The context associated with a Closure instance.
   //
   // Provided for instance kinds:
   //   Closure
-  //@Context closureContext [optional];
+  @Context closureContext [optional];
 
   // The referent of a MirrorReference instance.
   //
@@ -2472,7 +2515,7 @@
 }
 ```
 
-An _MemoryUsage_ object provides heap usage information for a specific
+A _MemoryUsage_ object provides heap usage information for a specific
 isolate at a given point in time.
 
 ### Message
@@ -3084,5 +3127,6 @@
 3.19 | Add 'clearVMTimeline', 'getVMTimeline', 'getVMTimelineFlags', 'setVMTimelineFlags', 'Timeline', and 'TimelineFlags'.
 3.20 | Add 'getInstances' RPC and 'InstanceSet' object.
 3.21 | Add 'getVMTimelineMicros' RPC and 'Timestamp' object.
+3.22 | Add `registerService` RPC, `Service` stream, and `ServiceRegistered` and `ServiceUnregistered` event kinds.
 
-[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
\ No newline at end of file
+[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/vm_service_lib/tool/service_undocumented.md b/vm_service_lib/tool/service_undocumented.md
index 4647939..376965e 100644
--- a/vm_service_lib/tool/service_undocumented.md
+++ b/vm_service_lib/tool/service_undocumented.md
@@ -128,53 +128,3 @@
 <!-- _getCpuProfileTimeline -->
 
 <!-- _getAllocationSamples -->
-
-streamId | event types provided
--------- | -----------
-_Service | ServiceRegistered, ServiceUnregistered
-
-### _registerService
-
-```
-Success _registerService(string service, string alias)
-```
-
-### EventKind
-
-```
-enum EventKind {
-  // Notification that a Service has been registered into the Service Protocol
-  // from another client.
-  ServiceRegistered,
-
-  // Notification that a Service has been removed from the Service Protocol
-  // from another client.
-  ServiceUnregistered
-}
-```
-
-### Event
-
-```
-class Event extends Response {
-  // The service identifier.
-  //
-  // This is provided for the event kinds:
-  //   ServiceRegistered
-  //   ServiceUnregistered
-  String service [optional];
-
-  // The RPC method that should be used to invoke the service.
-  //
-  // This is provided for the event kinds:
-  //   ServiceRegistered
-  //   ServiceUnregistered
-  String method [optional];
-
-  // The alias of the registered service.
-  //
-  // This is provided for the event kinds:
-  //   ServiceRegistered
-  String alias [optional];
-}
-```
diff --git a/web_socket_channel/BUILD.gn b/web_socket_channel/BUILD.gn
index be94a37..fe4501d 100644
--- a/web_socket_channel/BUILD.gn
+++ b/web_socket_channel/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for web_socket_channel-1.0.13
+# This file is generated by importer.py for web_socket_channel-1.0.14
 
 import("//build/dart/dart_library.gni")
 
diff --git a/web_socket_channel/CHANGELOG.md b/web_socket_channel/CHANGELOG.md
index 5240a85..d446637 100644
--- a/web_socket_channel/CHANGELOG.md
+++ b/web_socket_channel/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.14
+
+* Updates to handle `Socket implements Stream<Uint8List>`
+
 ## 1.0.13
 
 * Internal changes for consistency with the Dart SDK.
diff --git a/web_socket_channel/README.md b/web_socket_channel/README.md
index 7296560..c340775 100644
--- a/web_socket_channel/README.md
+++ b/web_socket_channel/README.md
@@ -6,16 +6,16 @@
 class, and [a similar implementation][HtmlWebSocketChannel] that wrap's
 `dart:html`'s.
 
-[stream_channel]: https://pub.dartlang.org/packages/stream_channel
-[WebSocketChannel]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel-class.html
-[IOWebSocketChannel]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel.io/IOWebSocketChannel-class.html
-[HtmlWebSocketChannel]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel.html/HtmlWebSocketChannel-class.html
+[stream_channel]: https://pub.dev/packages/stream_channel
+[WebSocketChannel]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel-class.html
+[IOWebSocketChannel]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel.io/IOWebSocketChannel-class.html
+[HtmlWebSocketChannel]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel.html/HtmlWebSocketChannel-class.html
 
 It also provides constants for the WebSocket protocol's pre-defined status codes
 in the [`status.dart` library][status]. It's strongly recommended that users
 import this library should be imported with the prefix `status`.
 
-[status]: https://pub.dartlang.org/documentation/web_socket_channel/latest/status/status-library.html
+[status]: https://pub.dev/documentation/web_socket_channel/latest/status/status-library.html
 
 ```dart
 import 'package:web_socket_channel/io.dart';
@@ -40,9 +40,9 @@
 socket, as well as [`closeCode`][closeCode] and [`closeReason`][closeReason]
 getters that provide information about why the socket closed.
 
-[protocol]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/protocol.html
-[closeCode]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/closeCode.html
-[closeReason]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/closeReason.html
+[protocol]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/protocol.html
+[closeCode]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/closeCode.html
+[closeReason]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/closeReason.html
 
 The channel's [`sink` property][sink] is also special. It returns a
 [`WebSocketSink`][WebSocketSink], which is just like a `StreamSink` except that
@@ -50,9 +50,9 @@
 `closeReason` parameters. These parameters allow the caller to signal to the
 other socket exactly why they're closing the connection.
 
-[sink]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/sink.html
-[WebSocketSink]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketSink-class.html
-[sink.close]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketSink/close.html
+[sink]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/sink.html
+[WebSocketSink]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketSink-class.html
+[sink.close]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketSink/close.html
 
 `WebSocketChannel` also works as a cross-platform implementation of the
 WebSocket protocol. Because it can't initiate or handle HTTP requests in a
@@ -63,10 +63,10 @@
 are used in the [`shelf_web_socket`][shelf_web_socket] package to support
 WebSockets in a cross-platform way.
 
-[new]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel-class.html
-[signKey]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/signKey.html
+[new]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel-class.html
+[signKey]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel/signKey.html
 [initial WebSocket handshake]: https://tools.ietf.org/html/rfc6455#section-4.2.2
-[shelf_web_socket]: https://pub.dartlang.org/packages/shelf_web_socket
+[shelf_web_socket]: https://pub.dev/packages/shelf_web_socket
 
 ## `IOWebSocketChannel`
 
@@ -82,7 +82,7 @@
 directly to a `ws://` or `wss://` URL, in which case
 [`IOWebSocketChannel.connect()`][IOWebSocketChannel.connect] should be used.
 
-[IOWebSocketChannel.connect]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel.io/IOWebSocketChannel/IOWebSocketChannel.connect.html
+[IOWebSocketChannel.connect]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel.io/IOWebSocketChannel/IOWebSocketChannel.connect.html
 
 ```dart
 import 'package:web_socket_channel/io.dart';
@@ -110,7 +110,7 @@
 directly to a `ws://` or `wss://` URL, in which case
 [`HtmlWebSocketChannel.connect()`][HtmlWebSocketChannel.connect] should be used.
 
-[HtmlWebSocketChannel.connect]: https://pub.dartlang.org/documentation/web_socket_channel/latest/web_socket_channel.html/HtmlWebSocketChannel/HtmlWebSocketChannel.connect.html
+[HtmlWebSocketChannel.connect]: https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel.html/HtmlWebSocketChannel/HtmlWebSocketChannel.connect.html
 
 ```dart
 import 'package:web_socket_channel/html.dart';
diff --git a/web_socket_channel/lib/src/copy/web_socket_impl.dart b/web_socket_channel/lib/src/copy/web_socket_impl.dart
index 6ac07cf..552b3e4 100644
--- a/web_socket_channel/lib/src/copy/web_socket_impl.dart
+++ b/web_socket_channel/lib/src/copy/web_socket_impl.dart
@@ -607,7 +607,7 @@
         onResume: _onResume,
         onCancel: _onListen);
     var stream =
-        _controller.stream.transform(_WebSocketOutgoingTransformer(webSocket));
+        _WebSocketOutgoingTransformer(webSocket).bind(_controller.stream);
     sink.addStream(stream).then((_) {
       _done();
       _closeCompleter.complete(webSocket);
@@ -709,7 +709,7 @@
     _readyState = WebSocket.OPEN;
 
     var transformer = _WebSocketProtocolTransformer(_serverSide);
-    _subscription = stream.transform(transformer).listen((data) {
+    _subscription = transformer.bind(stream).listen((data) {
       if (data is _WebSocketPing) {
         if (!_writeClosed) _consumer.add(_WebSocketPong(data.payload));
       } else if (data is _WebSocketPong) {
diff --git a/web_socket_channel/pubspec.yaml b/web_socket_channel/pubspec.yaml
index b4cdedc..6f7f490 100644
--- a/web_socket_channel/pubspec.yaml
+++ b/web_socket_channel/pubspec.yaml
@@ -1,5 +1,5 @@
 name: web_socket_channel
-version: 1.0.13
+version: 1.0.14
 
 description: >-
   StreamChannel wrappers for WebSockets. Provides a cross-platform
@@ -17,5 +17,5 @@
   stream_channel: ">=1.2.0 <3.0.0"
 
 dev_dependencies:
-  pedantic:
+  pedantic: ^1.0.0
   test: ^1.2.0